Shifting from VBScript or Unix to PowerShell

A couple of weeks ago at TechEd 2010, I delivered several sessions on PowerShell (the decks are still available for download at ConcentratedTech.com, by the way). In them, two distinct patterns emerged: Folks trying to treat PowerShell like VBScript, or like a Unix shell. You sort of can - but you're working way too hard.

Let's hit the VBScript aspect first. While PowerShell *offers* a robust scripting language (of less than 20 keywords, making it simple to learn), you often don't need to use it much. For example, in VBScript, the common pattern is to (1) get a bunch of something, (2) store them in a variable, and then (3) enumerate through them in a loop of some kind.

Dim FSO, folder, folders
FSO = CreateObject("Scripting.FileSystemObject")
folder =  FSO.GetFolder("C:\Users")
For Each folder In folders
   WScript.Echo folder.Name
Next

If you find yourself doing this in PowerShell, you're working too hard. This is better:

Dir c:\users | Select name

Accomplishes the same thing. PowerShell command pipelines are designed to cope with bunches of things, meaning you don't have to write loops and stuff nearly as often. If it *looks* like a script, it probably *is* a script, and you're probably working harder than you need to. That isn't always the case; PowerShell doesn't yet enjoy full coverage within the operating system, so sometimes you do have to fall back on the old-fashioned technique - but try not to.

Now, about the Unix thing: Someone asked, "is there an equivalent to grep in PowerShell?" That always makes me suspicious, so I always ask, "why?" One possible answer is, "I have a bunch of text log files I need to parse," such as from IIS or a firewall, and that's fine. I'll direct those folks to the Select-String cmdlet, which provides what grep-like capability PowerShell offers. The other possible answer goes something like this, "well, I need to run a command and pipe its output to a text file, and then I want to parse that text file to pull out just some of the output." Very common in Unix - and overkill in PowerShell. You see, there's no need to use text files as an intermediary between two commands, because PowerShell's pipeline already passes information in a universal data structure called "objects." 

For example, let's say you want to list all service that should be running (e.g., are set to start automatically), but which aren't running. In Unix, you might get a list of configured daemons, and pipe that to a file. Then you'd parse out the ones who had a "stopped" in their "status" column, perhaps, and pipe the remainder to a third command. In PowerShell, there's no need:

Get-WmiObject Win32_Service | Where-Object { $_.State -ne 'Running' -and $_.StartMode -eq 'Auto' }

Accomplishes the same thing. Want to try and start them?

Get-WmiObject Win32_Service | Where-Object { $_.State -ne 'Running' -and $_.StartMode -eq 'Auto' } | Start-Service

See? By utilizing these in-memory data structures ("objects"), you can avoid the need to parse text files. I don't have to figure out what info lives in what column - I just refer to the attribute (or column, or property, or whatever you want to call it) directly. Easier, less intermediate overhead, and more efficient.

Yeah, it takes some getting used to. That's why I encourage folks to *ask me questions,* through the FAQ submission feature on WindowsITPro.com (you'll find the FAQ item in the top menu). Answered questions appear on http://windowsitpro.com/go/DonJonesPowerShell; be aware that I write the FAQs about a month and a half in advance so that they can be edited, and appreciate your patience!

Also, don't forget: I've just launched ConTech Connect; if you're a past student of mine (even at a conference), register there if you'd like to submit questions to me personally. I'll take the most commonly-asked ones (the "frequent" ones, if you will) and add them to the FAQ here at WindowsITPro.com.

Please or Register to post comments.

What's PowerShell with a Purpose Blog?

Don Jones demystifies Windows PowerShell.

Blog Archive

Sponsored Introduction Continue on to (or wait seconds) ×