PowerShell: Take care with null arguments and SilentlyContinue…

I just had an excellent gotcha at work that took down one of our test servers.

I’m using PowerShell scripts as part of an msdeploy process to stop a service in the presync command so that the files can be updated, followed by yet more PowerShell starting the service back up again in the postsync command.

My script looked like this:

Get-Service $serviceName -ErrorAction SilentlyContinue | Stop-Service

I made two mistakes here and learned two valuable lessons.

Lesson 1 – Don’t misuse SilentlyContinue

For reasons I won’t bore you with, $serviceName wasn’t defined. Normally the interpreter would’ve halted proceedings and prevented anything from happening, but since I was eating all the errors it just went along and passed $null into Stop-Service. Which of course stopped all the services.

Yes, all of them.

Even Parental Controls. PARENTAL CONTROLS! THINK OF THE CHILDREN!

Since I wanted one specific service, I’ve now chosen to do something more like this:

$service = Get-Service | ?{ $_.ServiceName -eq $serviceName } | select -First 1

if ($service) {
$service.Stop()
}

This isn’t very “functional” and PowerShell experts will have more elegant and PowerShell-like ways to resolve this, but at least I’m not eating exceptions any more.

Lesson 2 – Be careful with null arguments

In that first example, what if $serviceName was defined, but was currently null? Run this for yourself and see:

Get-Service $null

That’s right, no error, and it returns ALL your services. Which in my case would’ve been piped into Stop-Service…

This is obvious when you think about it. “Get-Service $null” is exactly the same as “Get-Service”. The default behaviour for which being to return all services.

So beware when using variables as arguments – think about what the default behaviour is if those values are null.

Lesson 3 – Scripts are software too

I said there were 2 lessons, but I just thought of this one so I threw it in. I should have known better than to eat all the exceptions. I’d never do this in C#, for example:

try
{
// Do stuff
}
catch
{
// Om nom nom
}

So why did I allow myself to do it here? I think subconsciously I was thinking “It’s only a script” but of course that was a mistake. In future I will try and make sure I treat scripts with the same respect as any other software I write. Even a simple batch file could do untold damage if badly written, let alone the more intricate things that are possible with PowerShell.

About these ads

One thought on “PowerShell: Take care with null arguments and SilentlyContinue…

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s