PowerShell Pipe

Syndicate content
Two weeks (max) worth of chronologically merged posts from a selection of PowerShell bloggers
Updated: 1 hour 20 min ago

Get-HeadsUp | Register-TechnologyExchange@VMword2010

August 12, 2010 - 7:33am

Don’t miss the opportunity to meet part of the genuine Vmware PowerCLI team live!

 

Two parts session focuses on PowerCLI and Onyx.

 

More than 230 PowerShell cmdlets, along with documentation and samples in version 4.1.

Tips and tricks - the art of being efficient managing vSphere.

 

Hands-on lab: VMware vSphere™ PowerCLI

 

Bright new Onyx version with tons of fresh, cool features. For those who don’t know, Onyx is a standalone application that serves as a proxy between the vSphere Client and the vCenter Server. It monitors the network communication between them and translates it into an executable PowerShell code. You will be the first to see it before even its official release!


Pausing a Windows PowerShell Script to Receive Keyboard Input

August 12, 2010 - 3:01am
Summary : Pausing execution of a Windows PowerShell script to receive keyboard input can be as simple as using the Read-Host cmdlet. But other methods are available. Hey, Scripting Guy! I would like to pause a Windows PowerShell script and wait for user...(read more)

Parsing IIS Log ActiveSync Traffic for Information about Iphone IOS Versions Exchange 2003,2007,2010

August 12, 2010 - 1:30am
Last month i posted a script for getting the Iphone IOS version information for all users on a server using the Get-ActiveSyncDeviceStatistics cmdlet which worked okay but had one major flaw in that it doesn't pick up the updates to the O/S as pointed out in http://www.hedonists.ca/2010/07/22/blocking-the-iphone-part-i. So the only 100% way would be to parse the IIS logs where you can grab the same information about the devices as long as the cs-useragent is being include in the logs (if not you need to change this). This script is still useful for somethings and hopefully i should be able to re-purpose this to do something useful.

There are good and bad things about parsing logs, the good is that this technique should work on any version of Exchange including 2003 the bad is that if your log files are large then there are much better ways then using Powershell to parse them (such as logparser). But using PS does have a number of advantages and if your whiling to wait while the script runs then this one if for you. As i don't have a lot of access to Production Exchange servers at the moment the testing this script has had is very little but seems to work okay on a few old logs i had lying around if you have any problems please let me know. The base of this parser if from one of my other post which is a pretty reliable parser I've used all the time. Its been adapted to only look at specific ActiveSync traffic which should contain the useragent information. The rest of the script is from my first ActiveSync script along with a little custom object code to get all the information compiled into a report. This script also reports on Non-Iphone as well (although doesn't give you the IOS details for these).

I've included two different versions in the download the first script offers a little file selection gui to let you browse and select the log file your want this to run it against the second can be run unattended and would look for last file modified in the last 6 hours in the log directory you configured it to look in eg

get-childitem c:\inetpubogsogfiles\w3svc1\*.* | where-object{$_.LastWriteTime -gt (get-date).addhours(-6)} | foreach-object{
$fname = $_.FullName
}

* Note it will only run on one log file in the above example if you want to batch process a number of files then the rest of the code needs to be functionized.

I've put a download of this code here the code itself looks like.

[System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms")
$exFileName = new-object System.Windows.Forms.openFileDialog
$exFileName.ShowHelp = $true
$exFileName.ShowDialog()

$sendAlertTo = "mailbox@example.com"
$sendAlertFrom = "mailbox@example.com"
$SMTPServer = "smtp.example.com"

$appleCollection = @()
$appleverhash = @{ }
$hndSethash = @{ }

function addtoIOShash($inputvar){
$inparray = $inputvar.Split(',')
$v1 = $inparray[1].Substring(0,1)
$v2 = $inparray[1].Substring(1,1)
$v3 = $inparray[1].Substring(2,($inparray[1].Length-2))
$useragent = "{0:D2}" -f (([int][char]$v2)-64)
$apverobj = "" | select IOSVersion,IOSReleaseDate,ActiveSyncUserAgent,AppleBuildCode
$apverobj.IOSVersion = $inparray[0]
$apverobj.IOSReleaseDate = $inparray[2]
$apverobj.AppleBuildCode = $inparray[1]
$apverobj.ActiveSyncUserAgent = $v1 + $useragent + "." + $v3
$appleverhash.add($apverobj.ActiveSyncUserAgent,$apverobj)

}



#IOSVersion,Deviceid,ReleaseDate
addtoIOShash("1,1A543,Jun-07")
addtoIOShash("1.0.1,1C25,Jul-07")
addtoIOShash("1.0.2,1C28,Aug-07")
addtoIOShash("1.1,3A100,Sep-07")
addtoIOShash("1.1,3A101,Sep-07")
addtoIOShash("1.1.1,3A109,Sep-07")
addtoIOShash("1.1.1,3A110,Sep-07")
addtoIOShash("1.1.2 ,3B48,Nov-07")
addtoIOShash("1.1.3,4A93,Jan-08")
addtoIOShash("1.1.4,4A102,Feb-08")
addtoIOShash("1.1.5,4B1,Jul-08")
addtoIOShash("2,5A347,Jul-08")
addtoIOShash("2.0.1,5B108,Aug-08")
addtoIOShash("2.0.2,5C1,Aug-08")
addtoIOShash("2.1,5F136,Sep-08")
addtoIOShash("2.1,5F137,Sep-08")
addtoIOShash("2.1,5F138,Sep-08")
addtoIOShash("2.2,5G77,Nov-08")
addtoIOShash("2.2.1,5H11,Jan-09")
addtoIOShash("3,7A341,Jun-09")
addtoIOShash("3.0.1,7A400,Jul-09")
addtoIOShash("3.1,7C144,Sep-09")
addtoIOShash("3.1,7C145,Sep-09")
addtoIOShash("3.1,7C146,Sep-09")
addtoIOShash("3.1.2,7D11,Oct-09")
addtoIOShash("3.1.3,7E18,Feb-09")
addtoIOShash("3.2,7B367,Apr-10")
addtoIOShash("3.2.1,7B405,Jul-10")
addtoIOShash("4.0,8A293,Jun-10")
addtoIOShash("4.0.1,8A306,Jul-10")

$hndSethash.add("Apple-iPhone","IPhone")
$hndSethash.add("Apple-iPhone1C2","IPhone 3G")
$hndSethash.add("Apple-iPhone2C1","IPhone 3GS")
$hndSethash.add("Apple-iPhone3C1","IPhone 4")
$hndSethash.add("Apple-iPad","IPad")
$hndSethash.add("Apple-iPod","IPod Touch")

$CurrentDate = Get-Date




$fname = $exFileName.FileName
$mbcombCollection = @()
$FldHash = @{}
$usHash = @{}
$fieldsline = (Get-Content $fname)[3]
$fldarray = $fieldsline.Split(" ")
$fnum = -1
foreach ($fld in $fldarray){
$FldHash.add($fld,$fnum)
$fnum++
}

get-content $fname | Where-Object -FilterScript { $_ -ilike “*&DeviceType=*” } | %{
$lnum ++
write-progress "Scanning Line" $lnum
if ($lnum -eq $rnma){ Write-Progress -Activity "Read Lines" -Status $lnum
$rnma = $rnma + 1000
}
$linarr = $_.split(" ")
$uid = $linarr[$FldHash["cs-username"]] + $linarr[$FldHash["cs(User-Agent)"]]
if ($linarr[$FldHash["cs-username"]].length -gt 2){
if ($usHash.Containskey($uid) -eq $false){
$usrobj = "" | select UserName,UserAgent,Iphone,IphoneType,IOSVersion,IOSReleaseDate,AppleBuildCode
$usrobj.UserName = $linarr[$FldHash["cs-username"]]
$usrobj.UserAgent = $linarr[$FldHash["cs(User-Agent)"]]
if ($usrobj.UserAgent -match "apple"){
$apcodearray = $usrobj.UserAgent.split("/")
$usrobj.Iphone = "Yes"
$usrobj.IphoneType = $hndSethash[$apcodearray[0]]
$usrobj.IOSVersion = $appleverhash[$apcodearray[1]].IOSVersion
$usrobj.IOSReleaseDate = $appleverhash[$apcodearray[1]].IOSReleaseDate
$usrobj.AppleBuildCode = $appleverhash[$apcodearray[1]].AppleBuildCode
}
else{
$usrobj.Iphone = "No"
}
$usHash.add($uid,$usrobj)
$mbcombCollection += $usrobj

}
}
}


$tableStyle = @"
<style>
BODY{background-color:white;}
TABLE{border-width: 1px;
border-style: solid;
border-color: black;
border-collapse: collapse;
}
TH{border-width: 1px;
padding: 10px;
border-style: solid;
border-color: black;
background-color:#66CCCC
}
TD{border-width: 1px;
padding: 2px;
border-style: solid;
border-color: black;
background-color:white
}
</style>
"@

$body = @"
<p style="font-size:25px;family:calibri;color:#ff9100">
$TableHeader
</p>
"@



$SmtpClient = new-object system.net.mail.smtpClient
$SmtpClient.host = $SMTPServer
$MailMessage = new-object System.Net.Mail.MailMessage
$MailMessage.To.Add($sendAlertTo)
$MailMessage.From = $sendAlertFrom
$MailMessage.Subject = "iPhone Registrration Report"
$MailMessage.IsBodyHtml = $TRUE
$MailMessage.body = $mbcombCollection | ConvertTo-HTML -head $tableStyle –body $body
$SMTPClient.Send($MailMessage)

It’s Official next Florida PowerShell User Group Meeting – Monday, August 16th 6:30PM…

August 11, 2010 - 3:39pm

Yes, Everyone is welcome to our next PowerShell meeting – “Topic:  Working with Functions”

Topic:  Working with Functions…

Location:

New Horizons of South Florida
Ft. Lauderdale Office
100 S. Pine Island Rd
Plantation, FL 33324

954-572-8600
or register on our website:
http://www.flpsug.com/
Meeting starts at 6:30PM

Import a Gist into your PowerShell ISE profile

August 11, 2010 - 11:12am

I realised a few hours after posting my last entry about a PowerShell ISE profile script, that I failed to describe to people new to the ISE environment, how to include the script as part of their ISE profile so it is always available.

Simply explaining how to determine the path of your ISE profile by checking the value of the $Profile variable from within the ISE would be boring, so instead I wrote another script to automatically download the first script from GitHub, and add it to your profile.

This new script can simply be copied and pasted into the ISE’s Command Pane (Ctrl+D) and your profile will be opened and updated, ready to be saved. Once saved, you can either restart the ISE or simply run ” . $profile ” (without quotes) from the Command Pane.

You will hopefully notice in this new script, that my usual attention to neatness and verbosity has been replaced with terseness due to the purpose of this script being a use once and throw away item. I had considered writing it as a single line but quickly regained my senses.


Filed under: PowerShell

Automatic TFS Check Out for PowerShell ISE

August 11, 2010 - 4:13am

I work with a lot of PowerShell scripts, it’s the fun part of my job. I do most of my editing using the PowerShell ISE, primarily because it is the default, but also because it has great syntax highlighting, tab completion, and debug support. Additionally, all of my scripts are in source control: sometimes Mercurial, occasionally Git, but mostly Team Foundation Server (TFS).

The way TFS works though, is that all files in your local workspace are marked as read-only until you Check-Out for editing. When working on TFS-managed files in Visual Studio, the check-out is done automatically as soon as you begin typing in the editor. The PowerShell ISE however has no idea about TFS and will let you edit to your heart’s content until you eventually try to save your changes and it fails due to the read-only flag.

But I’ve developed a solution…

I’ve written a PowerShell ISE-specific profile script that performs a few simple things:

  1. Checks if you have the TFS client installed (eg Team Explorer).
  2. Registers for ISE events on each open file and any files you open later.
  3. Upon editing of a file, if it is TFS-managed then checks it out.

The end result is the same TFS workflow experience from within the PowerShell ISE as Visual Studio provides.


Filed under: PowerShell, TFS

Masking Passwords in Windows PowerShell

August 11, 2010 - 3:01am
Summary : With Windows PowerShell cmdlets, it is easy to mask passwords used when scripting remote applications. Hey, Scripting Guy! I need to be able to mask a password when running a Windows PowerShell script. I am attempting to convert my VBScript...(read more)

PowerGUI 2.2 public beta is now available!

August 10, 2010 - 11:59pm

Today we released a public beta of our upcoming PowerGUI 2.2 release.  This beta includes a very significant change to our debugger as well as compatibility support with version 1.4 of the Quest AD cmdlets.  Here are a few of the improvements that come with the new debugger:

  • Native support for the PowerShell 2.0 debugger, including command-line management of breakpoints using Disable-PSBreakpoint, Enable-PSBreakpoint, Get-PSBreakpoint, Remove-PSBreakpoint and Set-PSBreakpoint;
  • Advanced breakpoint support such as command and variable breakpoints through the PSBreakpoint cmdlets;
  • $MyInvocation support in scripts that you are debugging (this has been an issue we have wanted to fix for a long time)
  • Start-Job and Invoke-Command support in scripts that you are debugging (this was another issue that had to be worked around that is fixed by the new debugger);

This is the first public beta that we have had in a while, so I want to make sure everyone interested knows how the beta works.  It’s a pretty straightforward process, as follows:

  1. If you are interested in trying out the beta, go to the beta download page and follow the instructions to download and install the beta.  If you are using PowerGUI 2.1.1, it will automatically be upgraded when you install the beta.
  2. Use the beta just like you would use the previous version of PowerGUI.
  3. If you run into any issues, please notify us on the PowerGUI 2.2 public beta forum.

That’s pretty much it.  I should also note that auto-update from the beta version of PowerGUI 2.2 to the RTM version of PowerGUI 2.2 will be supported.

We’re looking forward to your feedback, so please download the beta and let us know what you think!

Kirk out.

Technorati Tags: PowerShell,PoSh,Poshoholic,PowerGUI,beta


Share this post:


Episode 121 - PowerScripting Podcast - Jay Dave from Microsoft on UAC and AppLocker

August 10, 2010 - 10:41pm

Jay Dave, Program Manager at Microsoft about UAC and AppLocker

News

Execute commands and scripts from anywhere including the office and remote locations, as well as from a Web browser or smart phone with PowerGUI Pro from Quest Software. With the MobileShell feature, administrators can quickly run commands to troubleshoot problems or make changes, even when away from your desk! This gives teams more flexibility to work remotely while traveling, and to leverage admins from other offices in case of an emergency.

·         Execute queries remotely to determine if services or processes are running

·         Restart services, processes, or entire servers

·         Check mailbox settings

·         Unlock user accounts

·         Reset passwords

·         Run custom scripts

Visit quest.com/powerguipro and see why PowerShell and Quest PowerGUI are the ultimate Windows management tools.

Interview This segment is brought to you by SAPIEN Technologies. Superhero: Phantom Resources


This segment is brought to you by ConcentratedTech.com.

Tips


This segment is brought to you by Serverfault.com!


Keep the Date September 8

August 10, 2010 - 8:37pm

MSDN Webcast: geekSpeak: PowerShell for .NET Developers with Doug Finke (Level 200)

In this episode of geekSpeak, Microsoft Most Valuable Professional (MVP) Doug Finke takes us on a deep dive into PowerShell from a developer’s point of view. Doug shows techniques for integrating/debugging PowerShell from and to C# code as well as using PowerShell with a Windows Presentation Foundation (WPF) application. He also addresses using reflection at the command line, object pipelining, and PowerShell’s REPL. This geekSpeak is hosted by Glen Gordon andRachel Appel.

The geekSpeak webcast series brings you industry experts in a "talk-radio" format hosted by developer evangelists from Microsoft. These experts share their knowledge and experience about a particular developer technology and are ready to answer your questions in real time during the webcast.

Corporate Powershell Module Repository – Part 1 – Design and Infrastructure

August 10, 2010 - 8:25pm
Modules – Modules – Modules

If you’ve ever had a Powershell conversation with me the chances are high that you’ve heard my agenda around modules. I think that the 2.0 module cmdlets were exactly what Powershell needed. I come from the land of Perl where modules are an integral part of the community. Well-formed reusable code is something Perl developers take a lot of pride in. Unfortunately, the Powershell community has been very delinquent in picking up the Microsoft implementation of modules. This is mainly due to the lack of a well-designed Internet repository that users can easily install and import from. While this is a difficult task that we have yet to take on in the Powershell community, it is a much easier task to take on in a corporate environment.

Unfortunately, I can’t disclose the name of the company I work for, but I can tell you it is very large with about 100,000 users and plenty of IT folks to support it. When I started there three months ago I was extremely surprised at how amazing their Perl repository and documentation was complete with wiki sites, in-house modules, and distribution of those modules through a globally distributed file system. This was a fountain of information to drink from. Then I went to the Powershell site: ugh – a well of cyanide! The home page still referred to it as Monad! The snapins that were installed to the distributed file system were versions behind, and the documentation really needed an overhaul that reflected the usage of both Powershell 1.0 and 2.0 together.

It was a daunting task, but I quickly volunteered to take it on. Sweating nights and weekends I not only redesigned the documentation, but I put together a module repository that I am extremely proud of. Here’s what I did:

Gathered Requirements

I first spoke with users of Powershell in the company to understand how it’s used, and to understand what ways a module repository could be helpful. I came up with the following requirements:

  1. The repository had to support multiple versions of the same module
  2. Users who were using Powershell as a shell expected to have the most recent version of a module loaded when using Import-Module
  3. Users who were writing scripts needed the ability to specify a version number of the module to use in order to ensure that a new version of a module does not break their script.
  4. The repository needed to be available globally by all workstations and servers
  5. The repository required robust documentation for each module.

I had one additional requirement that came from me: Use the built-in cmdlets for modules i.e. Import-Module and Get-Module

Leveraged Existing Infrastructure

The distributed file system they use is extremely custom and is AFS based. While my design could use any CIFS share it was nice to have something with such strict control. I can publish to a \dev workspace for testing. Users only have access to DEV if they have their machines configured to use it via the registry. After testing and development is complete I can lock the DEV instance of a module and publish the files to a read-only file system accessible by all users and servers in the company around the world. The read-only piece is key. If you wind up configuring your in-house module repository using my method I highly recommend making the repository read-only with only a few key accounts having access to publish.

For the remainder of this article we will call the published read-only share: \\powertoe\modulerepo\

Configure the Code Access Security Policy

This is the only piece that requires administrator privileges. Because the distributed file system we use is already leveraged heavily by other .NET groups within the company this part was already in place in our desktop and server builds. In order to allow .NET to trust a share so it can load .DLLs from it you need to modify the policy with caspol.exe. Caspol.exe can be found in your .NET directory, and documentation about it’s usage can be viewed here.

Here’s a quick batch script that will determine the proper directory to run caspol.exe from, and then call caspol.exe with the proper parameters to configure our system to trust the \\powertoe\modulerepo share:

@echo off setlocal for /f %%a in ('dir %windir%\Microsoft.Net\Framework\v* /b') do @call :caspol %windir%\Microsoft.Net\Framework %%a for /f %%a in ('dir %windir%\Microsoft.NET\Framework64\v* /b') do @call :caspol %windir%\Microsoft.Net\Framework64 %%a endlocal goto :EOF :caspol set sc_dotnetpath=%1 set sc_dotnetversion=%2 %sc_dotnetpath%\%sc_dotnetversion%\caspol -polchgprompt off %sc_dotnetpath%\%sc_dotnetversion%\caspol -m -ag 1 -URL "file://///powertoe/modulerepo/*" FullTrust %sc_dotnetpath%\%sc_dotnetversion%\caspol -polchgprompt on goto :EOF

This step is only necessary if you are either using snapins that you will convert to modules or if your modules load dlls of any kind.

Design the Folder Structure

This was a big hurdle to overcome. Because I needed to nail the versioning of modules for many different purposes I spent a lot of time toying with using the -version parameter of Import-Module. What a dead end that was! The -version parameter seems to have been an afterthought to versions: Documentation that doesn’t work and a backwards method of selecting the highest version of a module frustrated me to no end. You can read a little more of this digression here.

After throwing away “Import-Module -version” I came up with an elegant solution to the problem. I decided I could script the user’s $env:PSModulePath. If you are not aware of how modules become available to the built-in cmdlets Import-Module and Get-Module you should read:

Get-Help about_modules

To summarize the relevant parts: the environment variable PSModulePath holds the file paths that the built-in cmdlets look in to find modules that are available. For example if the PSModulepath is set to c:\modules and you have a directory in that path called ToeISE with a ToeISE.psm1 or ToeISE.psd1 file it will be an available module when you run:

Get-Module -ListAvailable

If it is in that list you can then load the module with the following:

Import-Module modulename

As I mentioned I did struggle with trying to use a folder structure like \\powertoe\modulerepo\modulename\version or even \\powertoe\modulerepo\modulename\version\modulename with the $env:PSModulePath pointing to \\powertoe\modulerepo, but nothing worked quite the way I needed it to. In the end I used the following configuration:

\\powertoe\modulerepo\modulename\version\modulename

Design the Profile

To fix the PSModulePath to point to the latest version of every module in the repository I added the path of the latest module to $env:PSModulePath through a quick one-line script:

Get-ChildItem \\powertoe\modulerepo\|where{$_.psiscontainer}|foreach {Get-ChildItem $_.fullname|Where{$_.psiscontainer}|sort -Descending|select -First 1}|foreach {$env:PSModulePath += ";" + $_.fullname}

or for better readability:

Get-ChildItem \\powertoe\modulerepo\|where{$_.psiscontainer}|foreach { Get-ChildItem $_.fullname|Where{$_.psiscontainer}|sort -Descending|select -First 1 }|foreach { $env:PSModulePath += ";" + $_.fullname }

In the end, however, I wrapped this one line in a script and published it to \\powertoe\modulerepo\modulerepo.ps1. I documented that users should dot (.) source this script in their profile. It’s a similar copy/paste operation, but it allows me to control the profile of our users if anything in the module repository ever needed to change.

. \\powertoe\modulerepo\modulerepo.ps1

There is one small problem with my method: It may not scale very well. As the module repository grows it is possible that the script that loads PSModulePath will be too cumbersome. If that ever happens I can modify modulerepo.ps1 to include the full path for each module. It would then be a part of the controlled distribution process of any module to update this script with the new version of the module uploaded. Rather than introducing a manual point of failure I decided to tackle this problem if the module repository ever grew large enough where it would impact performance. There is also the question of whether performance will ever be hindered by a PSModulePath that becomes too large. Again, a problem I am resolved to tackling down the road if it ever manifests. In the meantime, the above solution gives our users a nice way to use get-module -listavailable and import-module modulename to use the central repository. This works for the latest version of any module, but it doesn’t handle how to specify a version to use.

Controlling Versions in Scripts

The solution is really a no-brainer. Import-module supports the usage of paths with the -name parameter. So simply users are instructed to use the full path to the .psd1 in their scripts:

Import-Module -name \\powertoe\modulerepo\PowerCLI\4.1.0\PowerCLI.psd1

Because we control what gets distributed to the module repository we can enforce standards e.g. Must have a psd1 file, must have inline help with specific fields filled out, must use proper namespaces, etc. Perhaps I will share that bit of information at a later date with you, but I know that there’s something that will interest you much more than an article about best practices. If you read the above example for Import-Module you’ll see that I’m using it on a .psd1 file for PowerCLI – Wait a minute – Does that exist? Does that work? Can anyone guess what I will writing about in a future article?

Recap
  • Create share and publish modules to \\server\share\modulename\version\modulename
  • run caspol to trust \\server\share
  • Use the one-liner in your $profile:
Get-ChildItem \\server\share\|where{$_.psiscontainer}|foreach {Get-ChildItem $_.fullname|Where{$_.psiscontainer}|sort -Descending|select -First 1}|foreach {$env:PSModulePath += ";" + $_.fullname}
  • Use the following to view available modules:
Get-Module -listavailable
  • Use the following to import modules from the repository:
Import-Module modulename or Import-Module -name \\server\share\modulename\version\modulename\modulename.psd1 Modules – Modules – Modules

They are a cool powerful way of sharing your well-formed code. It is a great way to promote best-practices internally and enforce your policy on reusable code. They are also an amazing utility that lets you quickly browse and install other people’s code. I strongly suggest you start using them. Next stop, let’s do this on the Internet people – a real CPAN-like module repository!

In part 2 we will look at the developer guidelines I created for in-house modules in order to make them suitable for publishing in the repository.


PowerShell too hard?

August 10, 2010 - 3:39pm

In an article on the Windows IT Pro site - http://www.windowsitpro.com/article/commentary/Bridging-the-Developer-Admin-Gap.aspx – Paul Thurrott states

But the problem with PowerShell is that it's so powerful its indecipherable to admins. PowerShell is arguably a full-blown development environment. It consists of a command-line shell, a .NET-based, object-oriented scripting language, and a runtime engine that can optionally be embedded in other applications. For the typically overworked admins and IT pros, PowerShell might be a godsend if they could actually use it. But I was of the mind in 2002—as I am today—that most admins and IT pros have a completely different set of skills and are overworked as it is. To really take advantage of PowerShell, you need to be a developer or learn those skills too. And finding people who have credible administrative and developer skills is quite a trick. If you're such a person, maybe it's time to ask for a raise.

 

Now I disagree totally with the crux of this paragraph for a number of reasons:

  1. PowerShell is not a full-blown development environment. You can do practically anything .NET based with it but just because you can doesn’t mean you should
  2. I know of many Windows administrators who have picked up PowerShell and learnt enough, quickly enough to be very productive and re-pay the time spent learning it many times over. There  is a sufficient body of knowledge available through the web – including articles in Windows IT pro that a PowerShell beginner can find the information they need to help solve their problem
  3. You do not have to be a developer to really take advantage of PowerShell – or any other scripting language. PowerShell is particularly good for the admin as it abstracts much of the .NET code into the cmdlets. If you use a cmdlet you don’t need to know, or even care, what .NET class is being used in the back ground.
  4. How much of a developer do you have to be to string cmdlets on the pipeline and come up with a powerful piece of functionality that solves your business problems now

In 2006/2007 when PowerShell was just getting started I might of agreed that starting with PowerShell could be viewed as a steep learning curve. Four years later I think it is a lot easier – again Windows IT Pro have published a number of articles on PowerShell – with much more information available.

I would turn this on its head and state that if you are a Windows administrator that isn’t using PowerShell you are making your life more difficult that it needs to be.

How to Reuse Windows PowerShell Functions in Scripts

August 10, 2010 - 3:01am
Summary : When writing a Windows PowerShell script, code reuse can speed up the process. Ed Wilson discusses best practices for reusing code. Hey, Scripting Guy! I often write Windows PowerShell scripts, and when I need to use a function that I wrote...(read more)