Reputation: 468
I'm using Powershell and trying to use remove-item. Usually, the file will not be there in my scenario and that will generate an error and splash like 6 lines of red text into my output. That's very disruptive and I don't want to see anything in that case. But, if there's any other kind of error, like file can't be removed because it's in use, then I want to see that error. I thought I could use two catch statements: one with [filenotfoundexception] or something like like that, and another with no exception type to get everything else. But, none of the codes from the error text work as an exception type: "Unable to find type". What's the correct way to deal with this?
Upvotes: 6
Views: 14320
Reputation: 17161
John's answer is very good, no doubt about that.
However I think there's another important point that has been missed in this discussion... don't leave catch
to do all your work if you can program defensively and gracefully against known error scenarios (like yours).
$FileToDelete = "C:\temp\NotFoundGuv.nah"
# Does the file exist?
if (Test-Path -Path $FileToDelete) {
# Why yes it does - let's bin it off!
Remove-Item -Path $FileToDelete
}
Obviously if the Remove-Item
fails for any reason (e.g. permissions or a race-condition) then an exception is thrown.
Upvotes: 9
Reputation: 24430
To ensure the error goes to the catch block, include -ErrorAction Stop
.
To Find the type of the error, catch the error and retrieve the exception's type:
try {
Remove-Item -Path 'c:\IDoNotExist.txt' -ErrorAction Stop
} catch {
$_.Exception.GetType().FullName
}
To catch a specific type of error:
try {
Remove-Item -Path 'c:\IDoNotExist.txt' -ErrorAction Stop
} catch [System.Management.Automation.ItemNotFoundException] {
"Specific Exception Caught"
}
Errors not caught will still show as write-error
output per normal behaviour.
If you want to catch all exceptions, but handle those other exceptions differently, you can include the default catch:
try {
Remove-Item -Path 'c:\IDoNotExist.txt' -ErrorAction Stop
} catch [System.DivideByZeroException] {
"Specific Exception Caught"
} catch {
"Generic Exception Caught"
}
You can add additional catch blocks for additional exception types. If you have a capture for an exception type and its superclass, the superclass catch must come later (otherwise the superclass would catch the exception and the later catch block would never be used). e.g. this is valid:
try {
Remove-Item -Path 'c:\IDoNotExist.txt' -ErrorAction Stop
} catch [System.Management.Automation.ItemNotFoundException] {
"[System.Management.Automation.ItemNotFoundException]"
} catch [System.Exception] {
"[System.Exception]"
}
... whilst this is not:
try {
Remove-Item -Path 'c:\IDoNotExist.txt' -ErrorAction Stop
} catch [System.Exception] {
"[System.Exception]"
} catch [System.Management.Automation.ItemNotFoundException] {
"[System.Management.Automation.ItemNotFoundException]"
}
Finally, there are finally blocks; as you may be familiar with from C# and many other languages:
try {
Remove-Item -Path 'c:\IDoNotExist.txt' -ErrorAction Stop
} catch [System.Management.Automation.ItemNotFoundException] {
"[System.Management.Automation.ItemNotFoundException]"
throw #though we caught the exception we're now rethrowing it. This is useful in scenarios such as where we want to log that an exception's occurred, but still allow the exception to bubble up to a higher layer
} catch [System.Exception] {
"[System.Exception]"
} finally {
"Always do this after a try/catch, regardless of whether there was an error, we caught the error, or we rethrew the error"
}
"If any uncaught error exists (i.e. including rethrown errors from the catch block) we won't reach this... If there were no errors or all errors were handled and not rethrown, we will"
Side Note: There's also something called trap
for handling exceptions... More info on all this stuff on this blog. https://blogs.msdn.microsoft.com/kebab/2013/06/09/an-introduction-to-error-handling-in-powershell/
Upvotes: 13