VMware Cloud Community
Tileca99
Contributor
Contributor

How to catch VimExceptions properly?

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?

0 Kudos
3 Replies
LucD
Leadership
Leadership

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

0 Kudos
Tileca99
Contributor
Contributor

Yes I saw the discussion .

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.

0 Kudos
ykalchev
VMware Employee
VMware Employee

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

Yasen Kalchev, vSM Dev Team
0 Kudos