Honorary Scripting Guy Award

Yesterday, Microsoft’s Ed Wilson announced the Honorary Scripting Guys for 2016. I am honored and very proud to be the newest Honorary Scripting Guy, joining this year’s repeat winners: Sean Kearney, Teresa Wilson, and Will Anderson.

The Hey, Scripting Guy! blog is a resource that was an enormous part of my self-learning journey when I first got started with PowerShell, just as I am sure it was for you. Just having the opportunity to write posts and share information on HSG is a huge privilege. I still find to be a surreal experience every time I see my content go up. My HSG posts are tagged with my name, in case you want to check them out.

Earlier this month, Ed and his wife, Teresa, announced their upcoming retirement in March. I’d like to thank them both so much for their immeasurable, phenomenal contributions to PowerShell and the community. Ed and Teresa, we are going to miss you both tremendously. I hope retirement treats you both excellently, as you more than well deserve.


Invoking Pester and PSScriptAnalyzer Tests in Hosted VSTS


Pester and PSScriptAnalyzer are both fundamental tools for testing the effectiveness and correctness of PowerShell scripts, modules, and other PowerShell artifacts. While it is relatively convenient and straightforward to run these tools on a local development workstation, and even on owned/on-prem testing servers, it is somewhat more complicated to execute these tests in your own Microsoft-hosted Visual Studio Team Services environment.

Pester is an open source domain specific language developed originally by Dave Wyatt, which enjoys contributions from a variety of prominent members of the PowerShell community, as well as Microsoft employees on the PowerShell product team. Microsoft is a big enough fan of Pester that it comes with Windows 10, and reference it frequently in talks and written material. Pester is used for PowerShell unit testing.

PSScriptAnalyzer is a static code checker for PowerShell modules and scripts that checks the quality of code by comparing it against a set of rules. The rules are based on PowerShell best practices identified by the PowerShell team at Microsoft and the community. It is shipped with a collection of built-in rules but supports the ability to include or exclude specific rules, and also supports custom rule definitions. PSScriptAnalyzer is an open source project developed originally by the PowerShell team at Microsoft.

Lots of DevOps teams use the above tools together, along with their internally generated standards and style guide, to ensure that PowerShell code that is released into any environment meets their standards. By using Pester to ensure that a piece of code performs the tasks required, using PSScriptAnalyzer to inspect code for general best practice violations, and using a peer review process to validate that code conforms to our standards and style guidelines, you can rigorously test and ensure the quality and functionality of all PowerShell code that you produce.

As part of a PowerShell Release Pipeline, you may store your code in the source control portion of VSTS, hosted by Microsoft. I’d suggest you use the automated build and release components of VSTS to execute a series of tasks before deploying, and to deploy PowerShell code. Two of these tasks are running Pester tests and PSScriptAnalyzer. As a standard, don’t release builds if any part of either of these two tests fail.

In previous versions of VSTS, the hosted build service ran PowerShell 4.x. Because installing modules from the PowerShell Gallery (to get Pester and PSScriptAnalyzer module files so they may be run) requires PowerShell 5.0 or higher, it was necessary to use a third-party configured build step or perform some other hijinks that possibly compromised the integrity of a build. Now that VSTS runs PowerShell 5.0, we can run Pester, PSScriptAnalyzer, and many other helpful modules without exporting them with our other code, or using third-party build steps.

Continue reading


Does A String Start Or End In A Certain Character?

Can you tell in PowerShell if a string ends in a specific character, or if it starts in one? Of course you can. Regex to the rescue!

It’s a pretty simple task, actually. Consider the following examples

In the first two examples, I’m checking to see if the string ends in a backslash. In the last two examples, I’m seeing if the string starts with one. The regex pattern being matched for the first two is .+?\$ . What’s that mean? Well, the first part .+? means “any character, and as many of them as it takes to get to the next part of the regex. The second part \\ means “a backslash” (because \ is the escape character, we’re basically escaping the escape character. The last part $ is the signal for the end of the line. Effectively what we have is “anything at all, where the last thing on the line is a backslash” which is exactly what we’re looking for. In the second two examples, I’ve just moved the \\ to the start of the line and started with ^ instead of ending with $ because ^ is the signal for the start of the line.

Now you can do things like this.

Here, I’m checking to see if the string ‘bears’ ends in a backslash, and if it doesn’t, I’m appending one.

Cool, right?


Quick Tip: Validate The Length Of An Integer

A little while ago, I fielded a question in the PowerShell Slack channel which was “How do I make sure a variable, which is an int, is of a certain length?”

Turns out it’s not too hard. You just need to use a little regex. Consider the following example.

$v6 is an int that is six digits long. $v2 is an int that is only two inches long. On lines three and four, we’re testing to see if each variables match the pattern ‘^\d{6}$’ which is regex speak for “start of the line, any digit, and six of them, end of the line”. The first one will be true, because it’s six digits, and the second one will be false. You could also use something like ‘^\d{4,6}$’ to validate that the int is between four and six digits long.


PowerShell 10 Year Anniversary Code Golf Winners

For the PowerShell 10 Year Anniversary, Will Anderson (@GamerLivingWill on Twitter) and I (@MrThomasRayner on Twitter) ran a three-hole code golf competition on code-golf.com, a site developed by fellow MVP Adam Driscoll.

Here is the link to all the background info on the competition: https://github.com/ThmsRynr/PS10YearCodeGolf . Check this page out for links to the individual holes, too.

So, without further delay, let’s announce the winners!

Hole 1

The challenge was to get all the security updates installed on the local computer in the last 30 days and return the results in the form of a [Microsoft.Management.Infrastructure.CimInstance] object (or an array of them).

The winner of this hole is Simon Wåhlin. Here is their 46 character submission.

gcls *ix* gets the CimClass win32_quickfixengineering and % *mC*e gets the CimClassName property. gcim is an alias for Get-CimInstance which, as per the previous section, is getting the win32_quickfixengineering class. The results are piped into the where-object cmdlet where the property matching the pattern I*n (which happens to be InstalledOn) is greater than the current date, minus 30 days.

Hole 2

The challenge was to get the top ten file extensions in c:\windows\system32, only return 10 items and group results by extension.

The winner of this hole is Simon Wåhlin again. Here is their 42 character submission.

ls c:\*\s*2\*.* means Get-ChildItem where the path is c:\<any directory>\<a directory matching s*2>\<files, not directories> and this pattern only matches the path c:\windows\system32\<files>. This is piped into the foreach-object cmdlet to retrieve the property that matches the pattern E*n, which is the Extension property. The extensions are piped into the sort-object cmdlet, sorted by the property that matches the pattern c*, which is count, and returned in descending order. This is an array, and the items in positions 0-9 are returned.

There were shorter submissions for this hole that didn’t explicitly target c:\windows\system32 and therefore missed the challenge. You could not assume we were already on c: or running as admin, etc. Some solutions included folders in the results which also missed the challenge.

Hole 3

The challenge was to get all the active aliases that are fewer than three characters long and do not resolve to a Get- command. For this hole, even though it wasn’t in the Pester test, you had to assume that non-standard aliases might be on the system. That’s why we specifically mentioned that we didn’t want you to return aliases that resolve to Get-*, and the Pester test checked the ResolvedCommand.Name property of the aliases you returned.

To break some submissions that didn’t check what the aliases resolved to, you could just run New-Alias x Get-ChildItem to create a new alias of ‘x’ that resolves to Get-ChildItem.

The winner of this hole is EdijsPerkums. Here is their 24 character submission.

Get-Alias is passed an array of regex patterns, ?,?? which corresponds to one and two characters. The results are piped into the where-object cmdlet to isolate aliases whose property that matches the pattern Di* (DisplayName) doesn’t match Get.

Congratulations to all the winners! We will be in touch to get you your prizes. We hope you all had fun with this mini-competition. Don’t forget to check out all the terrific material from the PowerShell 10 Year Anniversary on Channel 9!


Quick Tip: Get All The Security Patches Installed On A Server Since A Specific Date

Recently, I needed to get a list of all the security patches I’d installed on a group of servers in the last year. It turns out that there’s a WMI class for this and it’s super easy to retrieve this info.

In the win32_quickfixengineering class, you’ll find all the security patches installed on a system. One of the properties is the InstalledOn attribute which more recent than a year ago.

If you have a list of servers to do this for, this is still really easy.

Just paste them into a here-string and execute this for each of them.


Using PowerShell To List All The Fonts In A Word Document

Recently I was challenged by a coworker to use PowerShell to list all the fonts in a Word document. It turned out to be easier than I thought it would be… but also slower than I thought it would be. Here’s what I came up with.

There could very well be a better way of doing this but this is what I came up with in a hurry. Line 1 declares a new instance of Word and line 2 opens the document we’re looking at. Then, for each word (which is handily a property of the open word document), we’re expanding the font property and selecting all the unique names of the fonts on line 3. Lines 4 and 5 close the document and quit Word.

So you can get something like this!

Get All The Fonts In A Word Document Via PowerShell


Quick Tip: Allow A Null Value For An Object That Doesn’t Normally Allow It

In the PowerShell Slack channel (powershell.slack.com) a question came up along the lines of “I have a script that needs to pass a datetime object, but sometimes I’d like that datetime object to be null”. Never mind that maybe the script could be re-architected. Let’s solve this problem.

The issue is, if you try to assign a null value to a datetime object, you get an error.

The solution is super easy. Just make the thing nullable.

This will return no output. So when you’re declaring the variable that will hold your datetime object, just make sure you make it nullable.

Just for more proof this works as advertised, try this.



Quick Tip: Copy The Output Of The Last PowerShell Command To Clipboard

I recently found myself poking around in PowerShell and going “oh, good now I want to copy and paste that output into an email/dialog box/tweet/notepad/another script/complaint box” and either trying to copy and paste it out of PowerShell or hitting the up arrow and piping whatever the last command was into Set-Clipboard. What a hassle.

So, I threw this small function into my profile.

You’ll need PowerShell 5.0 for this one (for Set-Clipboard). This just looks like gibberish though, what’s going on?

Well, clearly I’m defining a function named cc which is not a properly named PowerShell function but I’m being lazy. What does it do? Well it does r | scb.

r is an alias for Invoke-History which re-runs the last command you typed. Try it yourself.

scb is an alias for Set-Clipboard which means whatever came out of the last command will be the new contents of your clipboard.

The cool thing about this is it doesn’t just have to be text. Check out my other post about all the things Set-Clipboard can do.