Wednesday, July 23, 2008

Handling Errors in PowerShell

Powershell gives you a few ways to handle errors in your scripts.  The most powerful tool in your arsenal is the exception trap, I'm sure, but it's a bit complicated and I can't claim to be a master of PowerShell exceptions, but I'll go over that too.  We'll start off with something you'll use a lot more though, even though you may not know it.


PowerShell has a number of Preference Variables that you can use to determine the way it behaves.  If you have the v2 CTP version installed then you can run 'help about_Preference_Variables' to see the list, but for the rest of us use the link above.  $ErrorActionPreference sets the way PowerShell will respond when hitting a non-terminating error.  This won't affect errors that terminate a script.  

The allowable values for $ErrorActionPreference are 'Continue' (default), 'SilentlyContinue', 'Inquire', and 'Stop'.

Which errors are terminating and which aren't?  Well there's no definitive list, but take this example to show you how it works:

PS HKLM:\> dir


   Hive: Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE

SKC  VC Name                           Property
---  -- ----                           --------
  7   4 COMPONENTS                     {StoreFormatVersion, StoreArchitecture, PublisherPolicyChangeTime, LastScavengeCookie}
  4   0 HARDWARE                       {}
  1   0 SAM                            {}
Get-ChildItem : Requested registry access is not allowed.
At line:1 char:3
+ dir <<<<
 17   0 SOFTWARE                       {}
  9   0 SYSTEM                         {}

______________________________________________________

PS HKLM:\> $ErrorActionPreference = 'SilentlyContinue'
PS HKLM:\> dir


   Hive: Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE

SKC  VC Name                           Property
---  -- ----                           --------
  7   4 COMPONENTS                     {StoreFormatVersion, StoreArchitecture, PublisherPolicyChangeTime, LastScavengeCookie}
  4   0 HARDWARE                       {}
  1   0 SAM                            {}
 17   0 SOFTWARE                       {}
  9   0 SYSTEM                         {}

______________________________________________________

PS HKLM:\> $ErrorActionPreference = 'Inquire'
PS HKLM:\> dir


   Hive: Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE

SKC  VC Name                           Property
---  -- ----                           --------
  7   4 COMPONENTS                     {StoreFormatVersion, StoreArchitecture, PublisherPolicyChangeTime, LastScavengeCookie}
  4   0 HARDWARE                       {}
  1   0 SAM                            {}

Confirm
Requested registry access is not allowed.
[Y] Yes  [A] Yes to All  [H] Halt Command  [S] Suspend  [?] Help (default is "Y"): y
Get-ChildItem : Requested registry access is not allowed.
At line:1 char:3
+ dir <<<<
 17   0 SOFTWARE                       {}
  9   0 SYSTEM                         {}


As you can see, the default is to print an error and continue, while 'SilentlyContinue' will suppress error messages, which is similar to the old 'On Error Resume Next' in VBScript.

One nice side-effect of having this Preference Variable is that you can change the behavior for just one code block or function within your script.  Once the variable inside of the block goes out of scope, $ErrorActionPreference reverts to the original value.

PS HKLM:\> function suppress_errors ([string]$path) {
>> $ErrorActionPreference = 'SilentlyContinue'
>>  echo "`$ErrorActionPreference = $ErrorActionPreference"
>>}
>>
PS HKLM:\> echo "`$ErrorActionPreference = $ErrorActionPreference"
$ErrorActionPreference = Continue
PS HKLM:\> suppress_errors
$ErrorActionPreference = SilentlyContinue
PS HKLM:\> echo "`$ErrorActionPreference = $ErrorActionPreference"
$ErrorActionPreference = Continue


NOTE: You can also use the -ErrorAction (or -ea) switch that is ubiquitous across cmdlets with the same values if you want to change PowerShell's behavior for a particular command.

2 comments:

Joachim said...

That was very helpful, thx :)

Anonymous said...

Nice one !! Thanks