Author: Shane Corellian
Tobias Weltner wrote this article on the Powershell.com site. It is definitely worth the read. For those of you planning on implementing Powershell Version 2, pay special heed.
"When you search for PowerShell V2 downloads, you will find tons of articles and download links. Only some of them point to the correct final "RTM" link. A lot of people are still blogging about "CTP" versions which really were beta versions with limited functionality. Even worse, it turned out that these out-dated PowerShell versions are still up for download from the Microsoft Download center, so when you follow the "wrong" link, you could get the impression that these CTP versions really were official and up-to date releases."
I have been playing with V2 now for about 3 weeks and so far I am pretty excited. Extending Admin Arsenal with a good CLI is important and Powershell will definitely be the foundation on which it is built.
Photo by Tim Morgan
I was recently bitten by a PowerShell quirk that took me quite a while to find. It has to do with how PowerShell deals with the current directory when making .NET function calls. I created a script to make changes to an XML file that looked similar to this:
$xml = [xml](get-content "file.xml")
$xml.Parent.Node.Id = [system.guid]::newguid().tostring()
When I ran the script, the file didn't change. I couldn't for the life of me figure out why. This was the first time I was working the XML libraries in PowerShell and I was certain it must be due to how I was using the library. Finally, after about a half hour of searching I discovered that the change file was being saved to the original directory, not to the directory I had changed to. It turns out that when you change directories in PowerShell, you don't change the current directory in the environment and so the .NET libraries think you're still in the original directory. Since I read the file using PowerShell with get-content and saved using the .NET XML library, I was properly reading the file, but saving it in the wrong place.
This quirk is apparently deliberate, having something to do with enhancements in a future version of PowerShell which will allow suspending of jobs in the background. I'm not sure that this is the best way to deal with that eventuality, but there you go.
There are two ways around this problem. The first, and simplest is to use the resolve-path cmdlet:
echo $xml.Save(resolve-path "file.xml")
This will ensure that the full path to the file will be sent to the .NET class, ensuring that the file is saved in the correct location.
The second option, which may be preferable in some situations, is to change the directory using the .NET Directory class:
This will change the current directory in the environment. It's probably safer to use resolve-path, but it will not be sufficient if a .NET class must work on the current directory and you can't pass in another path.
One thing that always bothered me about the normal Windows command line was the lack of an equivalent to /dev/null in UNIX. When running a command whose output you wanted to ignore (i.e. not have it cluttering up your console window) you had to redirect it to a real file. This always seemed a bit sloppy to me, because you ended up with file laying around containing who knows what that you really just wanted to ignore.
Photo by Redvers
PowerShell, however, does have an equivalent. You can redirect to the built-in variable $null to get the same effect.
PS C:\> dir > $null
In addition to the $null variable you can also pipe output to the out-null cmdlet.
PS C:\> dir | out-null
This second version also has a little trick up its sleeve. Normally when running a GUI app from PowerShell, control is returned immediately to the command line and PowerShell doesn't wait for the GUI app to exit. This may not be what you want. For example, in my build scripts I have a program that generates the documentation, it's actually a GUI app that takes parameters and writes out the help files. I want my script to wait for this process to finish, so the normal behavior doesn't work for me. But, by piping the output of the GUI app to out-null then PowerShell will wait for the app to finish. You can see this yourself by running notepad.
PS C:\> notepad | out-null
If you have delayed getting into PowerShell, or if you have installed it but only piddled around a little, then please take note.
There is a PowerShell quick start guide available from Robert Sheldon. It provides six lessons which all build upon each other to get you comfortable using the tool and on the path to incorporating it into your daily tasks.
I recommend it for the beginner (don't worry, there are a lot experienced Windows admins who are new to this type of administration). The book is a bargain US$15.95 and is a quick read. It is provided as a .pdf file.
Unix-turned-Windows admins have waited a long time for a powerful cmd tool like PowerShell. Microsoft has delivered, however like anything worthwhile, Windows admins will need to meet Microsoft halfway and really learn the usefulness of this tool.
Remember, if you are repeatedly performing tasks, then automation is up your alley. PowerShell will help you achieve this.
For those of us who use WMI everyday here is a great blog at MSDN to learn tips and tricks with accessing WMI via PowerShell.
I found a tip to help me start using PowerShell to traverse my WMI database.
Give 'er a look.