Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Try, Catch, Finally blocks to catch Windows PowerShell errors related to reading the registry.
Hey, Scripting Guy! Yesterday you posted Update or Add Registry Key Value with PowerShell. Would it be easy to use Try, Catch, Finally blocks to know if I need to create the registry key or the registry key property? How can I do that? It doesn't seem very simple to me.
—AP
Hello AP,
Microsoft Scripting Guy, Ed Wilson, is here. The biggest challenge to using structured error handling in a Windows PowerShell script (beyond the most simple basics) relies on two things:
- Changing the ErrorActionPreference variable from the default of “Continue” to “Stop.”
- Knowing the actual name of the error that you want to catch.
The first, although not necessarily obvious, is required because attempting to read a missing registry key is not a “terminating error.” This means that an error message displays, but it does not halt the running Windows PowerShell script. What I need to do, is to cause non-terminating errors (those that would normally stop a Windows PowerShell script) to actually stop the script. This will then force the Windows PowerShell script to enter the Try, Catch, Finally blocks. In reality, it is really a simple value assignment. It is shown here:
$ErrorActionPreference = "stop"
Note Ashley McGlone wrote an excellent introductory article about Try, Catch, Finally blocks:
Using Try, Catch, Finally Blocks for PowerShell Error Handling.
The second challenge is not obvious at all. In fact, it is actually hidden. This is because in an attempt to make Windows PowerShell error messages easier to read, we actually hide the more complex aspects of those messages. Here is an example:
This might not look really simple, but it is less complicated than the full output. To find the full output of an error message, I need to pipe the output to Format-List and use the –Force parameter. Here is the expanded error message output:
Notice in the previous image that the Exception states it is an ItemNotFoundException:
System.Management.Automation.ItemNotFoundException
This is the exact name I need for my script to reference the fact that the registry key does not exist.
I add the registry key back in, but I delete the registry key property value. Now the $error[0] refers to a registry key property that is missing. Here is the error message I get from that:
Now I have all the information I need to create my framework to test a script.
I do not have to type everything if I don’t want to do so, because there is a built-in Windows PowerShell snippet that I can insert. All I do is start snippets (from the Edit menu) and select a Try, Catch, Finally snippet. It provides the following outline:
try
{
1/0
}
catch [DivideByZeroException]
{
Write-Host "Divide by zero exception"
}
catch [System.Net.WebException],[System.Exception]
{
Write-Host "Other exception"
}
finally
{
Write-Host "cleaning up ..."
}
I can then edit it to meet my needs. Here is the script I wrote:
$ErrorActionPreference = "stop"
$registryPath = "HKCU:\Software\ScriptingGuys\Scripts"
$Name = "Version"
$value = "1"
Try {
Get-ItemProperty -Path HKCU:\Software\ScriptingGuys\Scripts -Name version
}
Catch [System.Management.Automation.PSArgumentException]
{
"Registry Key Property missing" }
Catch [System.Management.Automation.ItemNotFoundException]
{
"Registry Key itself is missing" }
Finally { $ErrorActionPreference = "Continue" }
I make sure that the registry key property “version” is missing by using the Registry Editor:
I run the script, and the output says the registry key property value is missing:
I delete the entire registry key, run the script, and it states the registry key itself is missing. Cool, it works.
Now all I need to do is to copy this script to a new Tab, add in my code from yesterday's post. I only add what is required by the situation when adding a registry key or registry key property value. The modified script is shown here:
$ErrorActionPreference = "stop"
$registryPath = "HKCU:\Software\ScriptingGuys\Scripts"
$Name = "Version"
$value = "1"
Try {
Get-ItemProperty -Path HKCU:\Software\ScriptingGuys\Scripts -Name version
New-ItemProperty -Path $registryPath -Name $name -Value $value `
-PropertyType DWORD -Force | Out-Null
}
Catch [System.Management.Automation.PSArgumentException]
{
New-ItemProperty -Path $registryPath -Name $name -Value $value `
-PropertyType DWORD -Force | Out-Null }
Catch [System.Management.Automation.ItemNotFoundException]
{
New-Item -Path $registryPath -Force | Out-Null
New-ItemProperty -Path $registryPath -Name $name -Value $value `
-PropertyType DWORD -Force | Out-Null }
Finally { $ErrorActionPreference = "Continue" }
AP, that is all there is to using Try, Catch, Finally blocks when updating a registry key with Windows PowerShell. Join me tomorrow when I will talk about more cool Windows PowerShell stuff.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy