Capturing Errors in PowerShell Scripts

Have you ever been writing a Power Shell script, and when you go to test it, it runs through, you see a bunch of red error text that flies by too fast to read, and then it quits? Ok, so you can use the ISE to scroll back up and see what those errors were, but what if you're testing in a different environment - like an automated process on a server, or a server build. You're watching the process and you see the red errors, but it's gone before you can see what happened. It all works fine in the ISE, but something is different when it runs in its final location.

Well, here's what you can do...

The $error variable

If only I'd known this when I first started using Power Shell, I could have saved hours of wasted debugging time... but all that red error text gets added automatically to a built in Power Shell variable named $error.

Yes, it's that simple.

Example time!

Let's say you have this simple script:

$service = get-service -name dhcp
if($service.Status -ne "Running")
    #take some action

get-service -name fakeservice
if($service.Status -ne "Running")
#take some action

Since "fakeservice" doesn't exist on the computer on which we're running this script (maybe you mistyped the service name, maybe it only exists on certain computers - who knows), the output of this will be the following:

get-service : Cannot find any service with service name 'fakeservice'.
At line:8 char:12
+ $service = get-service -name fakeservice
+            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (fakeservice:String) [Get-Service], ServiceCommandException
    + FullyQualifiedErrorId : NoServiceFoundForGivenName,Microsoft.PowerShell.Commands.GetServiceCommand

Now, if this was actively running on a remote computer, you wouldn't necessarily know that part of the script failed. Even if you're watching it, the red text just flies by with no way to check what it said.
But if you make this small addition to the end of the script, you can log the errors, and check them later:

$error | out-file \\server\share\errorlog.txt

\\server\share\ can be any accessible and writable location you want - it could be a local path like c:\, or a centralized share

If you want to make the file unique, so that multiple computers running the script can all send their error log to the same centralized location, you could do something like this:

$error | out-file \\server\share\$ENV:Computername-errorlog.txt

Now the log file that is created will be named with a prefix of the computer name the script was running on, for example FileServer01-errorlog.txt.

Just don't leave your error logs in a place where management can see... otherwise they'll panic and call a 2 hour meeting to discuss business-forward solutions to reduce the impact of the current error situation!