In PowerShell, There Can be MORE Than One
I loved the movie "Highlander," not only for the Queen soundtrack but for it's awesome mythology (we're talking the original move, here, not the off-the-wall third installment involving aliens). Plus, the catchphrase: "THERE CAN BE ONLY ONE!" In PowerShell, however, there can be more than one. A lot more than one. And nobody loses their head! Actually, a lot of administrators do lose their heads, because when searching for examples of how to do something, you can run across so many variations. Consider these four commands, which all do exactly the same thing:
October 14, 2010
I loved the movie "Highlander," not only for the Queen soundtrack but for it's awesome mythology (we're talking the original move, here, not the off-the-wall third installment involving aliens). Plus, the catchphrase: "THERE CAN BE ONLY ONE!" In PowerShell, however, there can be more than one. A lot more than one. And nobody loses their head!
Actually, a lot of administrators do lose their heads, because when searching for examples of how to do something, you can run across so many variations. Consider these four commands, which all do exactly the same thing:
Get-Service -name *B* | Stop-Service Get-Service -name *B* | ForEach-Object { $_.Stop() } Get-WmiObject Win32_Service -filter "name LIKE '%B%' | [ CA]Invoke-WmiMethod -name StopService Get-WmiObject Win32_Service -filter "name LIKE '%B%' | [ CA]ForEach-Object { $_.StopService() }
The first approach is to use a batch cmdlet. Here, I’m using Get-Service to retrieve all services with a “B” in their name, and then stop them.
The second approach is similar. Rather than using a batch cmdlet, however, I’m piping the services to ForEach-Object, and asking it to execute each service’s Stop() method.
The third way is to use WMI, rather than the shell’s native service-management cmdlets. I’m retrieving the desired services (again, any with “B” in their name), and piping them to Invoke-WmiMethod. I’m telling it to invoke the StopService method, which is the method name that the WMI service objects use.
The fourth way uses ForEach-Object instead of Invoke-WmiMethod, but accomplishes exactly the same thing.
There's even a fifth way, which uses PowerShell's scripting language (specifically, the ForEach construct)! It looks a lot like the last approach:
$services = Get-WmiObject Win32_Service -filter 'name LIKE "%B%'"ForEach ($service in $services) { $service.StopService()}
And a sixth approach would be to convert this scripting-style approach with Get-Service, rather than Get-WmiObject. Lots of options - and the exact same results. I tend to start with the very first approach that I used above: Use cmdlets and pipelines, whenever possible. I'll fall back to the more-complex versions only if I can't do what I need using the earlier, easier-to-read approaches.
On the up side, having this flexibility makes PowerShell approachable to a wide audience. If you're a VBScript person, the very last example here is probably pretty familiar-looking; Unix folks and other command-line jockeys would doubtless appreciate the first, more command-line-friendly approaches. And none of them are wrong! But the diversity of methods can be confusing as you're learning the shell, because you run across all these different-looking examples as you're reading blogs (like this one) and other online examples.
Which approach do you favor? Is there yet another approach you might use instead of one of these six?
About the Author
You May Also Like