Book Review: Windows PowerShell 2.0 Best Practices
Author: Ed Wilson and Windows PowerShell Teams at Microsoft
Publisher: Microsoft Press
I have three main criteria for judging a book:
- Is it technically accurate?
- Does deliver the material it claims to deliver?
- Is worth the cost of purchase and the time I spend reading it?
Before diving into the review I have to point out a vested interest in the book in that I was one of people asked to contribute a sidebar to the book. There are a number of contributions from Microsoft PowerShell Team members; Microsoft consultants and PowerShell MVPs. Don’t skip the side bars when reading the book as they contain a lot of interesting information.
The book arrives with a large thud on the door mat as weighs in with a mighty 715 pages by the time the index is counted. These pages contain 17 chapters in five parts:
- Introduction – covers the Scripting Environment; PowerShell capabilities; AD capabilities and User Management
- Planning – covers Scripting Opportunities; Configuring Scripting Environment; Avoiding Pitfalls; Tracking Scripting Opportunities
- Designing – covers Functions; Help; Modules; Input and Output; Errors
- Testing and Deploying – covers Testing Scripts; Running Scripts
- Optimizing – covers Logging Results; Troubleshooting Scripts
This is a big book and a reader could legitimately expect it to be packed with best practices. There are a lot of places in the book where the words “best practice” are used but it is not easy to find a specific recommendation if, for instance, you wanted to find the recommended way to deliver help for a script or function. The accompanying CD contains a six page PDF file that gathers the best practices together on a chapter-by-chapter basis. This information should have been in the book as an appendix in the worst case or best still as a summary section at the end of each chapter.
It may be argued that there wasn’t space in the book but my reading shows plenty of areas that could be cut to make room such as:
- Table 2-1 – three pages listing the members of the Win32_Process object
- Table 2-2 – over a page listing members of the EventLogConfiguration class
- Table 2-3 – over a page listing the members of the Win32_PingStatus class
- Page 78-80 – multiple views of an Excel spread sheet and message dialogs
- Table 4-1 – over a page of AD schema object members
- Table 4-2 – over a page of ActiveDirectorySchema class members
- Page 111 – a page listing the
- Etc etc
There is a lot of repetition in the output shown for various commands that could have been edited down.
By all means supply the best practices as a printable quick reference but they should have been available in the book.
After reading the book my immediate thought was that I couldn’t decide who the book was aimed at or which version of PowerShell was being discussed. The title includes the phrase “PowerShell 2.0” but the book includes a lot of material that is aimed at PowerShell 1.0 for instance why spend time on Win32_PingStatus when PowerShell 2.0 has the Test-Connection cmdlet?
A total of 243 scripts are supplied on the CD. No, I didn’t count them I used
(Get-ChildItem -Filter *.ps1 -Recurse).count
The scripts in many cases are written to demonstrate a point rather than being useful for administrators. I wonder if the same points could have been
The lists of WMI providers for Windows Server 2003 and Windows XP are useful but a better aid would have been to extend this to cover Vista, Windows 7, Windows Server 2008 and Windows Server 2008 R2.
So having said all of that, how does the book stand on delivering best practice for using PowerShell 2.0. That’s a difficult one to answer because best practice can be very subjective. I don’t use aliases in scripts and tend to avoid them at the prompt. I especially abhor the use of % and ? as aliases for foreach-object and where-object. Other people think the only way to go is to alias everything. In my opinion the book doesn’t deliver PowerShell 2.0 best practice. I’ll give some examples to sho why I think that.
In chapter 2 the Get-Service cmdlet is discussed and Win32_Service is used to change the startmode of a service. This was an accepted, and good, technique in PowerShell 1.0 but in 2.0 I would use Set-Service. It has a –computername parameter so we can work with remote machines – don’t need to drop into WMI. Less code and less complicated = best practice.
On page 59 “With the presence of Ping.exe and the Win32_PingStatus WMI, you really do not need the Test-Connection cmdlet.” I find that statement unbelievable. Ping.exe returns text which we would then have to parse – bad practice. Test-Connection uses Win32_PingStatus but wraps it up and makes it easier to use.
The list of ADSI connection strings on page 68 is very useful information.
On page 77 the function has a [switch] parameter for debugging – not best practice, we’ll come back to that later.
In chapter 3 a lot of time is spent discussing getting information of an Excel spread sheet to use as input to user creation scripts. Why? Dump it to a CSV file – its easier, less coding and PowerShell works grate with CSV files on the pipeline.
Chapter 4 discusses querying Active Directory using an ADO database. its claimed to be the traditional method for querying AD – maybe in VBScript because we didn’t have anything else. In PowerShell 1.0 I would use a DirectorySearcher object – faster, more flexible and easier to work with. In PowerShell 2.0 this is even easier with the [ADSISEARCHER] type accelerator.
Chapter 5 looks scripting opportunities. One script checks the Operating System version. Why not go with
Get-WmiObject -Class Win32_OperatingSystem | select caption
It gives the version as a name so we don’t have to decipher the version numbers.
Chapter 6 spends a lot of time discussing ways to pass parameters into a function or script. Use the param statement! It gives maximum flexibility and power and provides consistency. Best practice is to be consistent not change because you only have one or two parameters. Also in chapter 6 why discuss function libraries when we have modules in PowerShell 2.0. More power + more flexibility = best practice.
Chapter 7 discusses using the System.random class. Why when we have a Get-random cmdlet in PowerShell 2.0. Using a cmdlet ahead of scripting should always be best practice.
Chapter 10 on help really misses the point. Why use here strings when we can use comment based help which isn’t actually mentioned in this chapter! When it surfaces in chapter 11 its referred to as “Help Function tags”. Never heard that phrase before and we find out more about it by using
More on $args in chapter 12. Use the param statement it is a better practice. Why discuss creating code to check the value of a parameter falls within a given range when we have a [ValidateRange()] option we can invoke on the parameter. As a generalisation the advanced function capabilities are not covered very well.
Would you really store a password in the Registry?
There is a coding error in the script on page 457. Compare with page 458.
When testing the syntax of scripts both PowerShell ISE and PowerGUI editor, among others, will supply clues as to where the errors can be found. If you want a good syntax check try using Test-Script from PowerShell Community Extensions 2.0. Also why write your own code to invoke debug or whatif when you can get them in advanced functions by using [CmdletBinding(SupportsShouldProcess=$true)]
Which brings up another point – why use filters when you have advanced functions?
Some general comments:
- Some of the figures – especially those showing PowerShell error messages are difficult to read.
- The appendices could for the most part be dropped.
- Appendix A could be generated with get-help *-* | ft name, synopsis –Wrap
- Appendix B is delivered by Get-Verb
- Appendices D & E are 40 pages of listings of WMI and .NET classes. Put them on the CD and put the best practice summary in the book.
- The appendix with WMI error messages is useful.
If the book is delivering best practice why discuss all the options. Supply the best practice.
Overall this book tries to cover all options for performing a task in PowerShell and doesn’t concentrate on PowerShell 2.0 as you would expect from the title. It feels like a book that was originally targeted at PowerShell 1.0 and had some of the PowerShell 2.0 bits shoe horned in – especially in the early chapters.
Judging against my criteria:
- Is it technically accurate? The scripts work but I don’t think they always conform to best practice. Some of the methods described in the book duplicate functionality that is already available in PowerShell which drags the mark down to 6/10.
- Does deliver the material it claims to deliver? I think the book, at least partially, fails on this point. I would want to be able to pick up a best practice book and find, easily and quickly, the recommended best practice for performing a PowerShell task. Can’t do this with the book in its current format. I can’t give more than half marks on this one 5/10.
- Is worth the cost of purchase and the time I spend reading it? I leant a few things from the book and some of the tables supply information that is difficult to track down. Some of the sidebars are especially useful. I’d struggle to justify more than 7/10.
Overall I would say that it’s a good idea for a book that doesn’t actually achieve what it tries to do. I would like to see a second edition but involving the PowerShell community to a greater extent so that a true consensus on PowerShell best practice could be made available.