Updated Compile-Help.PS1 and Neat PowerShell Scripting Tricks

One of my favorite PowerShell scripts of all time is Jeff Hillman’s Compile-Help. Instead of attempting to read the PowerShell help in a text window, Jeff’s outstanding script packages up all the help into a searchable, linkified, and easy to read Compiled HTML Help (.CHM) file. Especially if you are new to PowerShell, easily being able to read the PowerShell help, well, helps. I dropped my updated version of Compile-Help.PS1 on the PowerShell Code Repository.

As the original Compile-Help was for PowerShell 1.0, I updated it for proper PowerShell 2.0 help output. That required a few tweaks here and there, but wasn’t too hard to fix. As I was validating my updates, I noticed that there was a bug in how the original Compile-Help handled the Related Links section you see when doing a Get-Help with the –full parameter. As I was fixing that bug, I made sure the Related Links section includes the link to the TechNet version of the help for the command. Finally, I added a full index to the .CHM so it’s easier find things alphabetically.

All developers have been told to read code to learn, but truly the best way to learn is to fix bugs or add features in someone else’s code. Not only did Jeff solve a great problem, he wrote some outstanding code that anyone wanting to learn PowerShell could learn from. As I was digging through the code, two PowerShell tricks really popped out as things that were very interesting to me as a PowerShell beginner. Even though I’ve been using PowerShell full time for two years, I have mastered the pieces I need to get my job done very effectively with it, but have only begun to go deeper into PowerShell.

The first cool concept I liked is that the switch statement in PowerShell is very powerful, especially when creating scripts that do a lot of string processing. The following code shows setting up a switch statement add adding the –regex flag, which makes each “case statement” (for lack of a defined term from PowerShell) the regular expression you want to match.

[C:Usersjohn]>$a = “abc”,”def”,”hij”
[C:Usersjohn]>$a | ForEach-Object {
>>     switch -regex ($_)
>>     {
>>         “^a.{2}” { “$_ Starts with an A” }
>>         “.{2}j$” { “$_ Ends with a J” }
>>     }
>> }
>>
abc Starts with an A
hij Ends with a J

Thinking like a C++/C# developer, I had only been using a small fraction of the PowerShell switch statement capabilities. Reading the documentation for switch (in the compiled help file, of course), showed there were other special flags it processes as well

If you want to do simple pattern matching, use the –wildcard switch and you get a pattern matching that’s easier to deal with than full-blown regular expressions.

[C:Usersjohn]>$a | ForEach-Object {
>>     switch -wildcard ($_)
>>     {
>>         “a*” { “$_ Starts with an A” }
>>         “*j” { “$_ Ends with a J” }
>>     }
>> }
>>
abc Starts with an A
hij Ends with a J

In the code above, I used “*” to match zero or more characters, but if I wanted to match just a single character, the standard “?” would accomplish that. Also supported are character ranges such as “[a-c]” to match a, b, and c. All the wildcard matching for the switch statement works anywhere PowerShell accepts wildcards, like directory listings. To read more about wildcards, see the about_WildCard help.

If you want the case statements to match exactly in the switch, use the –Exact parameter and if you want items to be case sensitive, the –CaseSensitive parameter is your friend. There’s one more fascinating switch parameter, –File. At first, I didn’t realize how powerful –File was until I typed out an example.

[C:Usersjohn]>$a > .foo.txt
[C:Usersjohn]>type .foo.txt
abc
def
hij
[C:Usersjohn]>switch -wildcard -file .foo.txt {
>>     “a*” { “$_ Starts with an A” }
>>     “*j” { “$_ Ends with a J” }
>> }
>>
abc Starts with an A
hij Ends with a J

After redirecting the values in $a to a file, I specified the –file parameter to the switch statement and each line in the file was processed through the switch. That blew my mind the first time I realized what was happening.

The second trick I learned from Jeff’s code was a real brainteaser. As I was fixing the Related Links processing, I was seeing in the PowerShell ISE debugger the code initializing a variable, but it didn’t make any sense how the initialization occurred. After about two hours of reading PowerShell documentation, books, and help, the light bulb finally went off above my head.

[C:Usersjohn]>function MagicHappensHere ( $val ) {
>>     $val + 1
>>     $val + 2
>> }
>>
[C:Usersjohn]>MagicHappensHere ( 7 )
8
9
[C:Usersjohn]>$x,$y = MagicHappensHere ( 3 )
[C:Usersjohn]>$x
4
[C:Usersjohn]>$y
5

Again, my hardwired C++/C# brain failed me. A PowerShell function can return an infinite number of values because “function output consists of everything that isn’t captured.” If you look at the first call to MagicHappensHere, where there is no assignment to variables, you see the output from the function directly in the PowerShell window. The second call shows the assignment with each variable receiving the output for the function. The link to the quote is to Keith Hill’s blog as was part of his outstanding Effective Windows PowerShell series, which he bundled up into an outstanding eBook you can download.

As I’m always on the lookout for great PowerShell scripts to learn from, please let me know of any you would recommend. I’m slowly unwiring my brain from 20 years of C++/C# hard coding so it will take a lot of reading and debugging, but the power of PowerShell is motivating me to do it!

Stay Informed

Sign up for the latest blogs, events, and insights.

We deliver solutions that accelerate the value of Azure.
Ready to experience the full power of Microsoft Azure?

Atmosera is thrilled to announce that we have been named GitHub AI Partner of the Year.

X