Category Archives: Tools

Tracking down commands that are polluting your pipeline

In a recent forum post, someone was having trouble with a function that was outputting more values than he expected. We’ve all been there. He was having trouble debugging this, and I decided to see if I could find a way to narrow down the search in an automated fashion, rather than having to step through the code by hand.

The full article and code are up on my blog at

Working on a new PowerShell module: ProtectedData

I’m working on a new module intended to make it easier to encrypt secret data, and share it among multiple users and computers in a secure fashion. It’s not quite ready for “release” yet, but I’ve made it public on GitHub anyway, so I can start to get feedback early.

Check out my original blog post (link) for details. The GitHub repository is here.

SAPIEN’s new WMI Explorer Released

We all know that working with WMI/CIM can be frustrating. So little of it is documented, and it can be tough to find the class that has the exact info you need.

A long time ago, SAPIEN released a very nice WMI Explorer tool that, recently, was taken offline. The reason is that the company was producing an all-new, from-scratch replacement – and it’s now available.

Their new approach is pretty interesting. Rather than just live-browsing the local WMI repository or a remote computer’s repository, the tool can now go through the repo and actually create a local cache. That cache is optimized for searching, making it a ton easier to search not only for class names, but also for property names and more. Even property values! So if you know (for example) that “Windows 8.1″ is part of some property of some class, this tool can help you find where it is. It also provides in-product links to what online WMI documentation exists, making it quicker to get to that stuff.

Although the old tool was a freebie, this new one will set you back $40, and I imagine it’s included with the $789 kitchen-sink bundle the company sells. While I miss the free tool, this new one is significant enough that I’d pay for it. After all, money is what keeps the programmers at SAPIEN employed, so we can’t expect great tools for zero money. Frankly, this new WMI Explorer is one of the very, very, very, very few tools that’s going to earn a place in my base VM images that I use in classes – simply because it’s so useful. The ability to search for property values gives me a whole new approach to finding the exact WMI class I need.

It’s a well thought-out tool. Now, it’s not “zero footprint” like the old one – but the old one didn’t do nearly as much, like creating a local, searchable cache of the repo. Also, this isn’t something I’d install on all my servers. There’s no need – you install it on your computer, and let it reach out to key servers to discover their repositories. So it’s “zero footprint” on the server, which is all I care about. That cache means I can even browse a remote machine’s repo when I’m completely offline, like on an airplane working on a book. That’s a huge deal for me.

SAPIEN’s blog article on the software release includes another interesting fact: They plan to release a new line of smaller tools like WMI Explorer, and either sell them separately or as a community package. Cool! But what’s even cooler is this: “The proceeds from these tools will go towards supporting user groups and non-profit organizations.” Well, damn. So that $40 isn’t even funding the development of the tool per se, it’s funding (in part) your local user group. That’s awesome, and makes it well worth the standalone purchase if you don’t own the whole Software Suite already.

As usual, SAPIEN offers a free trial. Give it a whirl.

[UPDATED] Review: SAPIEN VersionRecall

I recently played around with SAPIEN’s VersionRecall, and thought I’d share a bit about the experience. As a note, SAPIEN provided me with a license key to use. VersionRecall is advertised as a simple, single-user version control system “for the rest of us.” There are no servers, no databases, and nothing complex, according to the marketing copy.

Setup is quick – a 3-screen wizard and you’re done. Installation took under a minute. When you first launch the product, it attempts to find all the places on your computer where you might store scripts, so that it can connect those to a version-control repository. You can skip that bit, but it only took a few moments on my virtual machine. It found my DSC scripts, my PowerShell modules, and several other places I’d dropped scripts. You then indicate where you’d like your version-control repository – this is where old versions of files will be saved. You can also pick a certificate, to have the software automatically sign scripts each time you make a new version. That’s a subtle and very cool feature – and it’s a way to make AllSigned a more convenient execution policy.

I selected an option to have my version control repository updated every day at 4:30pm. That seems to let the software capture a snapshot of any changed files at that time every day; it was clear that you could also manually submit an update to the repository using VersionRecall or Windows’ own File Explorer.

From there, you’re in an Explorer-like view. It includes a tab for each folder where you store scripts. I find that I like that approach a lot – I tend to organize my scripts that way. I’ve got my modules in one spot, some sample scripts in another, stuff I’m playing with in a third, and so on – so the tabbed approach fits my organizational style. You can open files for editing right there. I don’t have PrimalScript installed on this test machine, but files opened in the ISE just fine. Ribbon buttons let you open the shell, the ISE, or SAPIEN’s PrimalScript or PowerShell Studio products.



Here’s how this works: You have to manually submit changed files to the version-control repository, or wait for the daily check-in (remember, I set mine to 4:30pm). This doesn’t magically capture changes throughout the day. But, you can always manually submit an update if you’ve been making significant edits. That’s how most “big boy” source control systems work – only they don’t usually have an automatic daily-check in as a backup plan. VersionRecall does.

You can always compare the current version against a repository version – and it’s a very slick comparison view.



Once you’ve checked in a few versions, you can easily see the complete list, quickly see what each file contains, and either restore a previous version or copy it to a different location. You can also compare two versions to see what’s different.



Notably, VersionRecall doesn’t stick your files into a database or some proprietary storage. Your check-in files stay files, in their original formats. That means, if you ever need to do so, you can simply go to the folder where VersionRecall’s repository is, and grab the files yourself. It should also allow files to be indexed by Windows (for filetypes where it does that), found by Windows search, and so on.

Unfortunately, PowerShell Studio doesn’t seem to recognize VersionRecall as a source control provider (at least, it didn’t show up when I tried to configure source control in PowerShell Studio). That means you can’t use the integrated check-in/out controls in PowerShell Studio. Instead, you almost want to open files by using VersionRecall’s Explorer, save them in PowerShell Studio, and then submit them to the repository back in VersionRecall. That’s a shame; the automatic check-in/out in PowerShell Studio would make it all a bit simpler.

VersionControl uses a “Modern” user interface scheme for the most part. Its ribbon is pretty clean and well-organized, and the icons were meaningful. As with most recent SAPIEN products, you can change the theme to one of almost a dozen different styles, so you should be able to find something you like. Icons remain the same either way; all you’re changing is the “chrome” of the UI.

Not much else to say. For a product that bills itself as simple and easy, VersionControl certainly delivers. It does one thing, and it does it pretty well. It’s definitely easy – and there’s less excuse than ever for not using some kind of version control for your scripts. A FAQ on SAPIEN’s blog answers questions like why VersionRecall doesn’t check-in files automagically each time they change, how it compares to something like Git, and more.

[Update: I’ve removed the section on the license key and activation; SAPIEN’s Alex Riedel pointed out that I had some factual errors, because my observations were based on my use of a “real” license key that was issued for my particular use, not a “trial” key. I admit that I find software licensing uninteresting, and none of it has any impact on the usefulness of the software, which is what the article was meant to cover.]

VersionRecall sells for $179 as a standalone product, which includes a year of updates. I think that price might be a bit high, given what the product does. I expect, however, that most people are getting VersionRecall as part of a SAPIEN software bundle. For $789, for example, you get everything they make. For me, the perfect combo is PowerShell Studio and VersionRecall, which retails for $568.


Saving Passwords (and preventing other processes from decrypting them)

This question is nothing new: “How do I save credentials in PowerShell so I don’t have to enter a password every time the script runs?” An answer to that question has been in PowerShell for a very long time: you use the ConvertFrom-SecureString cmdlet to encrypt your password, save the resulting encrypted string to disk, and then later reverse the process with ConvertTo-SecureString. (Alternatively, you can use Export-CliXml, which encrypts the SecureString the same way.) For example:

# Prompt the user to enter a password
$secureString = Read-Host -AsSecureString "Enter a secret password"

$secureString | ConvertFrom-SecureString | Out-File -Path .\storedPassword.txt

# Later, read the password back in.
$secureString = Get-Content -Path .\storedPassword.txt | ConvertTo-SecureString

The ConvertFrom-SecureString and ConvertTo-SecureString cmdlets, when you don’t use their -Key, -SecureKey, or -AsPlainText switches, use DPAPI to encrypt / decrypt your secret data. When it comes to storing secrets with software alone (and without requiring a user to enter a password), DPAPI’s security is about as good as it gets. It’s not unbreakable – all of the encryption keys are there to be compromised by someone with Administrator access to the computer – but it’s pretty good.

You can see the details on how DPAPI works in the linked article, but here’s the long and short of it: By default, only the same user account (and on the same computer) is able to decrypt the protected data. However, there’s a catch: any process running under that user account can freely decrypt the data. DPAPI addresses this by allowing you to send it some optional, secondary entropy information to be used in the encryption and decryption process. This is like a second key that is specific to your program or script; so long as other processes don’t know what that entropy value is, they can’t read your data. (In theory, now you have a problem with protecting your entropy value, but this at least adds an extra layer that a malicious program needs to get around.) Here’s an excerpt from the article:

A small drawback to using the logon password is that all applications running under the same user can access any protected data that they know about. Of course, because applications must store their own protected data, gaining access to the data could be somewhat difficult for other applications, but certainly not impossible. To counteract this, DPAPI allows an application to use an additional secret when protecting data. This additional secret is then required to unprotect the data.

Technically, this “secret” should be called secondary entropy. It is secondary because, while it doesn’t strengthen the key used to encrypt the data, it does increase the difficulty of one application, running under the same user, to compromise another application’s encryption key. Applications should be careful about how they use and store this entropy. If it is simply saved to a file unprotected, then adversaries could access the entropy and use it to unprotect an application’s data.

Unfortunately, the ConvertFrom-SecureString and ConvertTo-SecureString cmdlets don’t allow you to specify this secondary entropy; they always pass in a Null value. For that reason, I’m putting together a small PowerShell script module to add this functionality. It can be downloaded from the TechNet repository. It adds an optional -Entropy parameter to both ConvertFrom-SecureString and ConvertTo-SecureString.

Since I was tinkering with those commands anyway, I also added an -AsPlainText switch to the ConvertFrom-SecureString command, in case you want to get the plain text back. This saves you the couple of extra commands to set up a PSCredential object and call the GetNetworkCredential() method, or make the necessary calls to the Marshal class yourself.

Import-Module .\SecureStringFunctions.psm1
$secureString = Read-Host -AsSecureString "Enter a secret password." 

# You can pass basically anything as the Entropy value, but I'd recommend sticking to simple value types (including strings),
# or arrays of those types, to make sure that the binary serialization of your entropy object doesn't change between
# script executions.  Here, we'll use Pi.  Edit:  The latest version of the code enforces the use of the recommended simple
# types, unless you also use the -Force switch.

$secureString | ConvertFrom-SecureString -Entropy ([Math]::PI) | Out-File .\storedPassword.txt

# Simulating another program trying to read your value using the normal ConvertTo-SecureString cmdlet (with null entropy).  This will produce an error. 
$newSecureString = Get-Content -Path .\storedPassword.txt | ConvertTo-SecureString 
# When your program wants to read the value, it can do so by passing the same Entropy value. 
$newSecureString = Get-Content -Path .\storedPassword.txt | ConvertTo-SecureString -Entropy ([Math]::PI)

#Display the plain text of the new SecureString object, verifying that it was decrypted correctly.
$newSecureString | ConvertFrom-SecureString -AsPlainText -Force

Getting a list of Windows Language Locales with Windows Powershell

I shall never profess to be a developer.   I just like finding answers.  

One of the challenges I had today was finding a list of Language locales in Windows.   I poked about and found an online list posted which could help me out with MDT and programming in the Locales for Non english versions of Windows and Office 365 cached downloads.

The problem was the list links from Microsoft weren’t current.   I’m certain there are updated versions (if you have them, email them please or add them to comments) but I went for a programmatic solution.     But I wanted to ask WINDOWS what list it had available, and I didn’t want to sit down with a Hex editor playing with an NLS file. 

Granted, there is probably a BETTER way, but this was quick and simple.   I went to and did a search for “Locale Table” online.   One of the very first links I found was for the “DataTable.Locale” property in .NET.


I could see it was a part of “System.Globalization.Cultureinfo” and decided to try something quick and simple in Windows Powershell, see if this could be natively accessed.

So into Windows Powershell I tried it as an accelerator



A smile crossed my face at this point, and I started to play.      I tacked on a ‘::’ and played with Tab Autocompletion to see what was available to play with out of the box.   First out of the list was ‘CurrentCulture’



“Oh Cool!” my eyes lit up.  I then wondered if there was a “Get” method available.   A little more online poking on MSDN confirmed this as part of the base Methods.


So I tested with a simple numeric id,  Number 1 (Really, I just took a shot to see if it would work)



Then i tried with a bad one, (again I was guessing at values)



Aha! So all I had to do to get a list of Locales was

Make Errors silent temporarily
Loop through all possible locale values
Capture the list


$locales=For ($lcid=0; $lcid –lt 20500; $lcid++) {  [System.Globalization.Cultureinfo]::GetCultureInfo($lcid)}

Granted this is a REALLY bad example of code.  I am tripping off a CRAP load of errors just to get what I want.  There might even be an easier way to find the information, i just find something “Quick and Dirty” (watching all my Developer friends cringe as overload the stack with errors)

Now after having gone through this process my good friend and fellow Windows Powershell MVP Shay Levy mentioned to me there was an easier way! 


Boy THAT was a treat to that as solution! I could even make it into a cheap and dirty Cmdlet (And I do mean Cheap and Dirty) by doing this

Function global:GET-CULTURE { [System.Globalization.Cultureinfo]::GetCultures(“AllCultures”) }


But now what I had was a simple object with the data captured.  I could Sort on it

$locales | SORT-OBJECT

Or export it out as a CSV file for easy reference later

$locales | EXPORT-CSV C:\Powershell\locales.csv

With this information finding the names of locales for my Office 365 and MDT deployments was now a piece of cake!

….and All thanks to the Power of Shell!