How To Test PowerShell Scripts With WhatIf
PowerShell is a full-scale command-line shell and scripting environment for the Windows server platform and the applications that run on it. Using PowerShell, administrators can automate repetitive or tedious tasks. Additional cmdlets, such as the Active Directory Module for PowerShell, provide an ever growing array of functions administrators can use to script everything from the simplest tasks to complex enterprise-wide changes.
Used correctly PowerShell 2.0 is a robust tool for system administration, but used incorrectly, it can be a powerful disruptor of an otherwise happy environment.
Testing PowerShell Scripts
Of course, no administrator with more than one day on the job would ever unleash an untested script onto an unsuspecting production environment. Like all system changes, PowerShell scripts should be developed on non-production systems and thoroughly tested before being implemented on real systems.
However, no amount of test environment simulation can replicate the complexities of a full-scale production environment. Worse, even a fully debugged script can contain some nasty surprises lurking to ruin the administrator’s weekend plan.
WhatIf PowerShell Parameter
Fortunately, PowerShell contains a very useful parameter called WhatIf.
The WhatIf switch runs a PowerShell script without actually running it. Rather than actually running the commands, the WhatIf switch only displays what the outcome of running the script would be if it were actually run.
What’s the Point?
Most administrators can’t just watch a script run and know for sure that it is doing what it is supposed to. However, there are plenty of times when watching the output of a running script can tell you that it is NOT running properly. A series of “Not Found” errors scrolling across the screen, for example, is an indicator that something is rotten in PowerScriptville.
Of course, eradicating that kind of error is something that should happen on a test system. It may take a while, but chasing down all the incorrect paths and typos in a non-production environment is a no harm, no foul, type event. But, what about those nightmares-in-waiting that don’t show up in that all-too-isolated testing environment?
There are plenty of ways a script error can slip through even a solid testing environment and create havoc in the production world. One way that constantly seems to impart painful experience and wisdom to even seasoned administrators involves “where” and his cousin “if.”
One of the things that makes PowerShell so useful is that an administrator can write the script so that it only affects desired targets. Examples would include, a script that only applies a
patch to systems without the latest updates, or a script that affects only users in a certain location or other objects with specific attributes. There are many ways to accomplish this including Where and If-Then commands.
The catch to using these commands is that while they may perform perfectly on the non-production test network, they have a way of matching far more than was intended when they get unleashed in a bigger environment.
The little script that was supposed to patch a dozen or so machines ends up inadvertently matching hundreds of systems. This is one of those times when the administrator can see that the script is not running as intended. The admin’s eyes grow wide with horror as the screen fills with the names of systems the script is matching when it was only supposed to apply to a handful of systems. A second later and you can almost hear the slow-motion, “Noooooooooo” as the admin’s hands reach desperately for the keyboard knowing that the damage has already been done.
After the fires have been put out, it will turn out that parameters that were specific enough to keep the script running on only the targeted systems didn’t take into account that in the production environment every machine in Iowa has an IA associated with the system, not just the machines used for internal audits.
Imagine the same scenario above, but with the WhatIf switch activated.
The same administrator will watch the same screen filling up with the names of systems being matched, but with one very important difference. Every line of output will be preceded by “What if:” telling the administrator that his weekend is not ruined and that the out of control script is only testing to see what would happen if the script were run.
Rather than panic, his face will twist into a scowl and the words, “What the << insert favorite epithet >>?” will calmly emerge from his mouth. After stopping the script, he’ll stare at the output for a minute or two and realize that all those machines in Iowa are inadvertently matching his script. He’ll tighten the conditions and re-run the script — with WhatIf enabled again — until everything looks right.
To use the WhatIf switch simply add –WhatIf to the end of your command line. Enabling that switch turns everything previously typed into a test, with the results of what would have happened if the commands were actually run appearing on the screen.
Keep in mind that WhatIf output cannot be piped to a file. WhatIf doesn’t actually run the commands so that output is not being generated. What displays on the screen is a direct to console message. However, for in-depth analysis, particularly in instances where a lot of things are happening to a lot of systems there may be a need to catch the data displayed by the WhatIf switch. In these cases, the Start-Transcript / Stop-Transcript cmdlets can be used to capture the information flowing to the screen.
Simply type Start-Transcript before running your WhatIf command and then type End-Transcript afterwards. You can direct the output to a specific file with the –path switch.
To avoid frustration, do NOT (out of habit) add the –WhatIf switch to the Start-Transcript (or End-Transcript) commands or you’ll spend hours chasing your tail trying to find a transcript file that doesn’t exist.
Not that I know anyone who has done anything like that.
What other ways do you use WhatIf? What are your favorite testing tricks?