Author Archives: Dave Wyatt

About Dave Wyatt

Dave Wyatt is a Microsoft MVP (PowerShell) and a member of's Board of Directors.

Announcing our 2015 PowerShell Heroes

The nominations are in, and the votes are tallied!

PowerShell Heroes is our way of recognizing the people who are making significant contributions to the PowerShell community, but who haven’t received any other formal recognition (such as Microsoft’s MVP Award). In many cases, these are the rising stars we hope to see receive an MVP someday, but in all cases they’re out there, working hard to make a difference. They were nominated by their peers, and selected by the 2014 PowerShell Hero honorees.

We’ve got nine PowerShell Heroes this year, so without further ado:

$heroes | Get-Random -Count $heroes.Count
  • Stéphane Van Gulick (@stephanevg):  Stéphane’s blog got a lot of attention in this year’s nominations. He’s also organizing a PowerShell User Group, and has several useful PowerShell scripts that are freely available to download.
  • Adam Bertram (@adbertram):  Adam is also an extremely active blogger. His main site is , but we’ve also seen articles from him on MCPMag. Aside from the general PowerShell love, Adam’s sharing a ton of knowledge about how to use PowerShell in tandem with System Center ConfigMgr, and he’s got some great career- and community-focused content as well.
  • Micky Balladelli got a ton of love from the French-speaking PowerShell community this year, receiving more nominations than any other individual. His blog can be found at , and in particular, his “First Steps” article ( has been praised for helping systems administrators to learn PowerShell, even those who are completely new to scripting / programming. Toujours PowerShell!
  • Mike Laughlin:  As far as we can tell, Mike is actually a robot, who needs no sleep and is dedicated to helping people out on the TechNet forums. Seriously, the man’s racked up over fifty thousand points in less than two years, with more than half of his posts being tagged as either answers or helpful by the community. However, it’s not just about the numbers. His posts are friendly and he follows up on them, and it’s extremely common to see posters making comments like this in his threads: “Sweet! This is EXACTLY what I’m looking for, Thank you so much!”
  • Nickolaj Andersen (@NickolajA):  Like Adam, Nickolaj has a particular focus on System Center ConfigMgr (as you might have guessed from his blog URL: .) However, that involves lots of PowerShell, and there’s plenty of it on his blog (including many free scripts for download.) What we saw in his nominations, though, was how much time Nickolaj puts into personal communication with the community: emails, Skype chats, you name it. He’s out there, helping people to get things done.
  • Matt Johnson (@mwjcomputing):  Matt is the founder of the Southeast Michigan PowerShell User Group, and the lead developer of the PoshSec security framework. He’s heavily involved in communities – speaking and volunteering at conferences, doing podcasts, etc. – for both Systems Administration and Infosec. (something which, frankly, we all need to learn more about. Been paying attention to the news for the last year or two?) His blog can be found at .
  • Bob McCoy is constantly helping people to solve problems over at and SpiceWorks. At any given time, you can fire up the or forums, and we’d be very surprised if you didn’t see multiple threads with “Latest post by Bob McCoy” listed in both.
  • June Blender (@juneb_get_help):  If you use PowerShell, June has helped you, whether you know it or not! When she worked for Microsoft, she was responsible for much of the built-in documentation that we get by running the Get-Help command. She’s also always been active in blog posts and on Twitter, spreading the joy of PowerShell. These days, she’s a Technology Evangelist over at SAPIEN, where she continues to do so.
  • Craig Duff is extremely active in the PowerShell forums over at SpiceWorks, usually the first person to respond to questions there. His solutions have been praised as clean, efficient and easy to understand, and there are lots and lots of them! (437 posts marked as “Best Answer”, as of this writing). His blog can be found at

Congratulations to our 2015 PowerShell Heroes!!

Accepting Nominations for 2015 PowerShell Heroes

It’s that time of year again: we’re looking for nominations for new PowerShell Heroes! The PowerShell Hero program is our way of giving recognition to people who are contributing to the PowerShell community, but who have not yet received some other similar award, such as Microsoft’s MVP or VMware’s vExpert. This will be the second year for the program; in January of 2014, we recognized Teresa Wilson, Mark Schill, Francois-Xavier Cat, Martin Pugh, and Dave Wyatt.

We will be accepting nominations for the 2015 Heroes until December 15th, 2014. After that date, we will go over the nominations, and the honorees will be announced in January.

Who can I nominate? Anyone you want, except current or past MVPs, Microsoft employees, Microsoft Regional Directors, or others who have been formally recognized for their community contributions.

How do I nominate them? Send an email to [email protected]. We need the person’s name or online handle, and some links to their contributions. Also describe in 100-500 words why they’re your PowerShell Hero. Please put “PowerShell Hero” in the subject line of your email.

How many people will be recognized? We don’t have a fixed number.

What will honorees receive? Online recognition; we’ll be publishing an online directory of Heroes.

Must someone re-qualify every year? This isn’t like the MVP program – it’s a recognition with no benefits. So there’s nothing to “qualify” for. In future years, the previous year’s honorees will select the next year’s honorees, so you’re prohibited from being recognized in sequential years.

How can I think of who to nominate? Think about who has helped you with PowerShell problems. Did someone help you solve something through a discussion forum? Did someone’s blog post give you that “aha!” moment? Did someone spend a massive amount of time putting together a PowerShell event that really helped you? Those are the heroes we want to recognize. Again, past and present MVP award recipients are not eligible – they’ve already been recognized.


Proxy Functions for Cmdlets with Dynamic Parameters

I came across an interesting problem today while working on the Pester module: how do you create a proxy function for a Cmdlet which has dynamic parameters? I needed a solution which would automatically reproduce the original cmdlet’s dynamic parameters inside a PowerShell function, and which would work on PowerShell 2.0 if at all possible. The full post and solution can be found on my blog at

DSC Pull Server on Windows Server 2008 R2

Recently on the forums, a community member mentioned that they were having trouble setting up a Server 2008 R2 machine as a DSC pull server. It turns out, this is possible, but you have to install all the prerequisites yourself, since the Add-WindowsFeature DSC-Service command doesn’t do it for you on the older operating system.

Refer to this blog post for the checklist.

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.

Community Brainstorming: PowerShell Security versus malicious code

A couple weeks ago, some malicious PowerShell code was discovered in the wild, dubbed the “Power Worm” in the Trend Micro article that originally publicised the malware. Matt Graeber has done a great analysis of the code on his blog. In the comments for that blog post, we started discussing some options for locking down PowerShell, preventing it from being used in this type of attack. (Unfortunately, Execution Policy is currently no barrier at all; PowerShell.exe can simply be launched with the -Command or -EncodedCommand parameters, bypassing ExecutionPolicy entirely.) Matt’s idea is to have PowerShell run in Constrained Language mode by default, similar to how it works on the Windows RT platform.

This post is to engage some community discussion on the topic; please do so in this thread:

What are your thoughts on this topic? Do you feel that PowerShell.exe needs some additional security features to try to prevent it from being used in this sort of malware? What impact would these ideas have on your normal, legitimate uses of PowerShell (if any)? How would you suggest minimizing that impact while still making it more difficult for PowerShell malware to execute?

Cmdlets or Advanced Functions?

I’ve posted a poll to get a feel for the PowerShell community’s preference on this. Compiled Cmdlets offer much better performance than the equivalent PowerShell advanced function, which can be a very valuable thing if you need to process large sets of data in your scripts. The other side of that coin is that in order to make changes or review the code of a Cmdlet, you need to start working with C# (and likely Visual Studio as well.) Which do you feel is more important when downloading a module: performance, or sticking with familiar PowerShell code?

The poll is over on my blog.

Thread Synchronization (lock statement) in PowerShell

While reading today’s “Hey, Scripting Guy!” blog post by Boe Prox, I learned that it is possible to have multiple threads / runspaces accessing the same live objects in a PowerShell session, something I had previously thought was not possible. Seeing that, I decided to write a “lock” statement for PowerShell, which can be necessary in some circumstances. See the original blog post for the function and more information.

PowerShell and System.Nullable<T>

While helping to answer a question about Exchange cmdlets today, I came across something interesting, which doesn’t seem to be very well documented.

A little background, first: in the .NET Framework (starting in Version 2.0), there’s a Generic type called System.Nullable<T>. The purpose of this type is to allow you to assign a value of null to Value types (structs, integers, booleans, etc), which are normally not allowed to be null in a .NET application. The Nullable structure consists of two properties: HasValue (a Boolean), and Value (the underlying value type, such as an integer, struct, etc).

A C# method which accepts a Nullable type might look something like this:

int? Multiply(int? operand1, int? operand2)
    if (!operand1.HasValue || !operand2.HasValue) { return null; }

    return operand1.Value * operand2.Value;

("int?" is C# shorthand for System.Nullable<int> .)

PowerShell appears to do something helpful, though potentially unexpected, when it comes across an instance of System.Nullable: it evaluates to either $null or an object of the underlying type for you, without the need (or the ability) to ever access the HasValue or the Value properties of the Nullable structure yourself:

$variable = [Nullable[int]] 10

$variable.GetType().FullName   # System.Int32

If you assign $null to the Nullable variable instead, the $variable.GetType() line will produce a “You cannot call a method on a null-valued expression” error. You never see the actual System.Nullable structure in your PowerShell code.

What does this have to do with Exchange? Some of the Exchange cmdlets return objects that have public Nullable properties, such as MoveRequestStatistics.BytesTransferred. Going through the MSDN documentation on these classes, you might expect to have to do something like $_.BytesTransferred.Value.ToMB() to get at the ByteQuantifiedSize.ToMB() method, but that won’t work. $_.BytesTransferred will either be $null, or it will be an instance of the ByteQuantifiedSize structure; there is no “Value” property in either case. After checking for $null, you’d just do this: $_.BytesTransferred.ToMB()

PowerShell Gotcha: UNC paths and Providers

PowerShell’s behavior can be a little bit funny when you pass a UNC path to certain cmdlets. PowerShell doesn’t recognize these paths as “rooted” because they’re not on a PSDrive; as such, whatever provider is associated with PowerShell’s current location will attempt to handle them. For example:

Set-Location C:
Get-ChildItem -Path \\$env:COMPUTERNAME\c$

Set-Location HKLM:
Get-ChildItem -Path \\$env:COMPUTERNAME\c$

The first command works fine (assuming you have a c$ share enabled and are able to access it), and the second command gives a “Cannot find path” error, because the Registry provider tried to work with the UNC path instead of the FileSystem provider. You can get around this problem by prefixing the UNC path with “FileSystem::”, which will make PowerShell use that provider regardless of your current location.

On top of that, commands like Resolve-Path and $PSCmdlet.GetUnresolvedProviderPathFromPSPath() don’t normalize UNC paths properly, even when the FileSystem provider handles them. This annoyed me, so I spent some time investigating different options to get around the quirky behavior. The result is the Get-NormalizedFileSystemPath function, which can be downloaded from the TechNet Gallery. In addition to making UNC paths behave, this had the side effect of also resolving 8.3 short file names to long paths (something else that Resolve-Path doesn’t do.)

The function has an “-IncludeProviderPrefix” switch which tells it to include the “FileSystem::” prefix, if desired (so you can reliably use cmdlets like Get-Item, Get-Content, Test-Path, etc., regardless of your current location or whether the path is UNC.) For example:

$path = "\\$env:COMPUTERNAME\c$\SomeFolder\..\.\Whatever\..\PROGRA~1" 
$path = Get-NormalizedFileSystemPath -Path $path -IncludeProviderPrefix 
Set-Location HKLM: 
Get-ChildItem -Path $path | Select-Object -First 1 

FileSystem::\\MYCOMPUTERNAME\c$\Program Files 
    Directory: \\MYCOMPUTERNAME\c$\Program Files 
Mode                LastWriteTime     Length Name 
----                -------------     ------ ---- 
d----         7/30/2013  10:54 AM            7-Zip 

Revisited: PowerShell and Encryption

Back in November, I made a post about saving passwords for your PowerShell scripts. As I mentioned in that article, the ConvertFrom-SecureString cmdlet uses the Data Protection API to create an encrypted copy of the SecureString’s contents. DPAPI uses master encryption keys that are saved in the user’s profile; unless you enable either Roaming Profiles or Credential Roaming, you’ll only be able to decrypt that value on the same computer where the encryption took place. Even if you do enable Credential Roaming, only the same user account who originally encrypted the data will be able to read it.

So, what do you do if you want to encrypt some data that can be decrypted by other user accounts?

The ConvertFrom-SecureString and ConvertTo-SecureString cmdlets have a pair of parameters (-Key and -SecureKey) that allow you to specify your own encryption key instead of using DPAPI. When you do this, the SecureString’s contents are encrypted using AES. Anyone who knows the AES encryption key will be able to read the data.

That’s the easy part. Encrypting data is simple; making sure your encryption keys don’t get exposed is the trick. If you’ve hard-coded the keys in your script, you may as well have just stored the password in plain text, for all the good the encryption will do. There are several ways you can try to save and protect your AES key; you could place it in a file with strong NTFS permissions, or in a database with strict access control, for example. In this post, however, I’m going to focus on another technique: encrypting your AES key with RSA certificates.

If you have an RSA certificate (even a self-signed one), you can encrypt your AES key using the RSA public key. At that point, only someone who has the certificate’s private key will be able to retrieve the AES key and read your data. Instead of trying to protect encryption keys yourself, we’re back to letting the OS handle the heavy lifting; if it protects your RSA private keys well, then your AES key is also safe. Here’s a brief example of creating a SecureString, saving it with a new random 32-byte AES key, and then using an RSA certificate to encrypt the key itself:

    $secureString = 'This is my password.  There are many like it, but this one is mine.' | 
                    ConvertTo-SecureString -AsPlainText -Force

    # Generate our new 32-byte AES key.  I don't recommend using Get-Random for this; the System.Security.Cryptography namespace
    # offers a much more secure random number generator.

    $key = New-Object byte[](32)
    $rng = [System.Security.Cryptography.RNGCryptoServiceProvider]::Create()


    $encryptedString = ConvertFrom-SecureString -SecureString $secureString -Key $key

    # This is the thumbprint of a certificate on my test system where I have the private key installed.

    $thumbprint = 'B210C54BF75E201BA77A55A0A023B3AE12CD26FA'
    $cert = Get-Item -Path Cert:\CurrentUser\My\$thumbprint -ErrorAction Stop

    $encryptedKey = $cert.PublicKey.Key.Encrypt($key, $true)

    $object = New-Object psobject -Property @{
        Key = $encryptedKey
        Payload = $encryptedString

    $object | Export-Clixml .\encryptionTest.xml

    if ($null -ne $key) { [array]::Clear($key, 0, $key.Length) }

Notice the use of try/finally and [array]::Clear() on the AES key’s byte array. It’s a good habit to make sure you’re not leaving the sensitive data lying around in memory longer than absolutely necessary. (This is the same reason you get a warning if you use ConvertTo-SecureString -AsPlainText without the -Force switch; .NET doesn’t allow you to zero out the memory occupied by a String.)

Any user who has the certificate installed, including its private key, will be able to load up the XML file and obtain the original SecureString as follows:

    $object = Import-Clixml -Path .\encryptionTest.xml

    $thumbprint = 'B210C54BF75E201BA77A55A0A023B3AE12CD26FA'
    $cert = Get-Item -Path Cert:\CurrentUser\My\$thumbprint -ErrorAction Stop

    $key = $cert.PrivateKey.Decrypt($object.Key, $true)

    $secureString = $object.Payload | ConvertTo-SecureString -Key $key
    if ($null -ne $key) { [array]::Clear($key, 0, $key.Length) }

Using RSA certificates to protect your AES encryption keys is as simple as that: Get-Item, $cert.PublicKey.Key.Encrypt() , and $cert.PrivateKey.Decrypt() . You can even make multiple copies of the AES key with different RSA certificates, so that more than one person/certificate can decrypt the data.

I’ve posted several examples of data encryption techniques in PowerShell on the TechNet Gallery. Some are based on SecureStrings, as the code above, and others use .NET’s CryptoStream class to encrypt basically anything (in this case, an entire file on disk.)

Error Handling draft available

There was quite a bit of interest in the upcoming free Error Handling ebook during the PowerScripting Podcast on Thursday. It’s still in a very early draft form, but I’ve posted it to the GitHub repository for anyone who wants to brave the unedited waters and get a preview of the content.

Feedback is welcome, particularly on the technical content. Don’t worry about the presentation / organization so much, as those are likely to change once we go through a review and edit process anyway. You can post comments on GitHub, or contact me directly at [email protected].

Automatic formatting of code for posting on forums

Hello everyone,

As you may know from past experience or from reading the Forums Tips and Guidelines sticky, there are a couple of quirks with the forum software we’re using here related to CODE tags and backtick characters. The forum software treats backticks as special characters, which is quite annoying if your code contains any of them, and you’ll find that using PRE tags will give you much better results than CODE, particularly if someone tries to copy and paste your code into another window.

I’ve added a function to my PowerShell ISE profile which avoids these headaches by taking the code in the ISE’s active window, escaping it in such a way that the forum will display it properly, wraps it in PRE tags (and also adds a blank comment line to the beginning and end of the code, to make copy / paste easier), and pipes the results to the clipboard. All I have to do is press F7 and then paste into the forum window. The function was even used to post itself here, which is about as good of a success indicator as I can think of.

The lines of this function may wrap in the blog post; there is a downloadable copy on the TechNet Gallery at

Edit: Looks like the handling of code formatting / HTML escaping on the blog posts has changed since it was originally posted, and the function posted here was displaying all sorts of double-escaped characters that it shouldn’t have. Please use the TechNet download link to find the proper code.

Revisited: Script Modules and Variable Scopes

Last week, I demonstrated that functions exported from Script Modules do not inherit their caller’s variable scopes, and how you could get around this by using the method $PSCmdlet.GetVariableValue().

It didn’t take me long to decide it was very tedious to include this type of code in every function, particularly when considering the number of preference variables that PowerShell has. (Check out about_Preference_Variables some time; there are quite a few.) I’ve just converted this approach into a function that can be called with a single line, and supports all PowerShell preference variables. For example, the Test-ScriptModuleFunction from the original post can be written as:

function Test-ScriptModuleFunction
    param ( )

    Get-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState

    Write-Host "Module Function Effective VerbosePreference: $VerbosePreference"
    Write-Verbose "Something verbose."

You can download the Get-CallerPreference function from the TechNet Gallery. It has been tested on PowerShell 2.0 and 4.0.