When invoking a simple command like
get-vm -name foo
and the cmdlet throws an exception as the requested virtual machine does not exist, how can that exception be properly handled in a powershell script?
I already found out how to catch all exceptions:
trap {
write-host "EXCEPTION"
continue
}
get-vm -name foo -ea stop
That's not a very clever solution in my opinion, because other exceptions occuring later in the script will use the same exception handler.
By checking $error[0].exception.gettype().fullname right after invoking the get-vm cmdlet I realized that the exception's type is VMware.VimAutomation.Types.VimException and therefore tried to use the trap command like this:
trap \[VMware.VimAutomation.Types.VimException\] { ..... }
The exception type seems to be recognized correctly by powershell but the exception handler is not being invoked at all.
Am I missing something? Is there a proper way to handle the different VMware exceptions separately?
Did you see ?
The Get-Stat seems to intercept the exception and take a default action.
The only way I could find to get into a trap was to use the -ErrorAction parameter to override the default behaviour of the Get-Stat cmdlet.
But then you don't see the VimException information anymore in the trap block.
Perhaps an area for improvement in a future VITK build ?
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
That's exactly why I used the get-vm cmdlet like this:
get-vm -name foo -ea stop
(ea is the abbreviation for ErrorAction)
The problem is (as you already stated) that you can't see the type of exception in your trap block anymore. Therefore you are not able to handle different exceptions in different ways. Obviously this does not only apply to the get-stat cmdlet but to any other cmdlet as well.
This should definitely be improved in a future realease of VITK.
Hi,
The reason why you can not trap all VITK errors is because some of them are non-terminating PS error. This means that PS just reports the error and the command keeps running. As you already know you can change default non-terminating errors behavior with the -ErrorAction parameter or $ErrroActionPreference env var.
If you set ErrorAction to Stop PS does stop the exception and throw exception BUT: it throws System.Management.Automation.ActionPreferenceStopException exception and unfortunately the exception that cause this error do not present as InnerException.
However the original error message still present in the ActionPreferenceStopException and you can get it from there. Here is what I found in some PS blogs:
trap [http://System.Management.Automation.ActionPreferenceStopException|http://System.Management.Automation.ActionPreferenceStopException] { $msg = $_.Exception.Message -replace '^.+Stop: ' Write-Host $msg continue } get-vm -name foo -ea stop
I think better practice here is not to set ErrorAction to Stop but to examine $error variable. If ErrorAction is != stop $error contains the correct VimException that we throw so you can implement your custom error handling logic. Even more you can set -ErrorVariable parameter of the cmdlet and you can get only error from the cmdlet but not all errors stored in $error variable:
get-vm -name foo -ErrorVariable myErrors -ErrorAction Continue if ($myErrors.Count -gt 0) { #Examine last exception $e = $myErrors[0].exception if ($e -is [http://VMware.VimAutomation.Types.VimException|http://VMware.VimAutomation.Types.VimException]){ Write-Host "VimException occured: " + $e.Message } }
And finally: Why we mix non-terminating and terminating error and how you can determine which errors are terminating which are not?
Examine the following case:
Get-VM | Set-VM -GuestId foo
"foo" is invalid GuestId value and the command line will fail for all VMs (entire pipeline). So this should be terminating error.
But:
Get-VM | Start-VM
Start VM will fail for all started VMs but will power on all stoped VMs. In this case Start-VM will report non-terminating error for all started VMs.
I hope this explanation will help you to handle error handling task which turns out to be not quite easy.
Regards,
Yasen