As you write PowerShell scripts, it is important that you include error handling. Most of the time, this involves the use of Try/Catch statements. The tricky thing with Try/Catch is that you can only catch a terminating exception. There are a few cmdlets that by design will throw a terminating exception. But you have no way of knowing in advance. The best way to guarantee your Try/Catch block will work is to set the common -ErrorAction parameter to Stop. Only then are you guaranteed a terminating exception and that the code in your Catch block will run.
ManageEngine ADManager Plus - Download Free Trial
Exclusive offer on ADManager Plus for US and UK regions. Claim now!
However, there is another situation where this can be tricky, and this is a question that came up the other day. How can you create a terminating exception for a file not found situation?
For example, you might try code like this:
Try { Test-Path Foo:\Bar.txt -ErrorAction Stop } Catch { Write-Warning "I failed" }
When you run this code, you'll get False. The code in the Catch block never executes. This is because the Test-Path cmdlet writes a boolean (True/False) value to the pipeline. If the file or path doesn't exist that isn't an error. Although. you can make it one. Here's a variation on the preceding code.
$path = "Foo:\Bar.txt" Try { if (-Not (Test-Path $path)) { Throw "Failed to find the $path" } } Catch { Write-Warning "I caught an exception" $_ }
This works.
Personally, I would use a simple If statement. But obviously I can't speak to everyone's use cases.
But perhaps instead of using Test-Path you might consider a different cmdlet.
$path = "Foo:\Bar.txt" Try { Resolve-Path -Path $path -ErrorAction Stop } Catch { Write-Warning "I caught an exception" $_ }
Resolve-Path is intended to resolve wild-card characters in a path. If the path doesn't exist, the cmdlet will generate an exception. In my Try/Catch block I am forcing it to be terminating.
By the way, you could also use Convert-Path. One thing to be aware of is that these cmdlets will write objects to the pipeline, which may be exactly what you need. You may need to convert or resolve a path into a true file system path maybe to run some non-PowerShell command against it.
$path = "$env:windir\notepad.exe" Try { $rPath = Resolve-Path -Path $path -ErrorAction Stop } Catch { Write-Warning "I caught an exception" $_ } Write-Host "Using $rPath" -ForegroundColor green
One file option is to use Get-Item.
$path = "Foo:\Bar.txt" Try { [void](Get-Item -Path $path -ErrorAction Stop) } Catch { Write-Warning "I caught an exception" $_ }
In this case I don't need the actual file object so I'm casting the results of the command as nothing.
I'm not going to tell you that any one of these techniques is better than the other. It truly depends on the overall needs of your scripting project. I encourage you to read full cmdlet help and examples for the commands I've shown here. There may be additional parameters that can help you fine-tune your testing and error handling.