2

I had a strange Problem occurring in one of my PowerShell scripts today:

Enviroment Information: the PowerShell script im talking about is being called by a VBScript.

if($VM -eq "Yes") {
    Add-PSSnapin VMware.VimAutomation.Core
    Connect-VIServer -Server $VMHost -User $VMUser -Password $VMPassword
    $Snapshot = $null
    Try {
        $Snapshot = New-Snapshot -Name $NameofSnapshot -VM $ServerName -Memory
        $CurrentPatchingState = "1;$Servername;Status=1;$(Get-Date -format 'dd.MM.yyyy hh:mm:ss') Created Snapshot" | Out-File -Filepath  "C:\$Servername.txt" -Append -encoding ASCII 
    } Catch [system.exception] {
        $CurrentPatchingState = "2;$Servername;Status=2;$(Get-Date -format 'dd.MM.yyyy hh:mm:ss') Wasnt able to take a Snapshot - Aborting" | Out-File -Filepath  "C:\$Servername.txt" -Append -encoding ASCII 
        Disconnect-VIServer -Server $VMHost -Confirm:$false
        exit
    }

    if ($Snapshot -eq $null) {
        $CurrentPatchingState = "2;$Servername;Status=2;$(Get-Date -format 'dd.MM.yyyy hh:mm:ss') Wasnt able to get a Clean Snapshot - Aborting" | Out-File -Filepath  "C:\$Servername.txt" -Append -encoding ASCII 
        Disconnect-VIServer -Server $VMHost -Confirm:$false
        exit
    }
}

Today the script failed at this part. The log file showed:

2;xxxxxxxxxxxxxxx;Status=2;18.01.2015 11:01:51 Wasnt able to take a Snapshot - Aborting
2;xxxxxxxxxxxxxxx;Status=2;18.01.2015 11:01:51 Wasnt able to get a Clean Snapshot - Aborting

How can this occur, since the script should have stopped at the first catch?

Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
Ceuse
  • 23
  • 7
  • You shouhd use break in a try bloc, exit isn't a powershell keyword. See that relating post : http://stackoverflow.com/a/23703056/381149 – Loïc MICHEL Jan 19 '15 at 08:24
  • possible duplicate of [Terminating a script in PowerShell](http://stackoverflow.com/questions/2022326/terminating-a-script-in-powershell) – Loïc MICHEL Jan 19 '15 at 08:24
  • 1
    perhaps i didnt make myself clear enough, i wanted the hole script to stop thats why i used Exit: This will "exit" the currently running context. If you call this command from a script it will exit the script. The Script Terminated, but at the Second Exit not the first. – Ceuse Jan 19 '15 at 08:49
  • The exit is within a `[scriptblock]` which is it's own context the `exit` left that script block 'early' and returned to the parent context, the script itself... the 2nd exit is in the context of the script and so terminates correctly. – Djarid Apr 15 '16 at 13:13

2 Answers2

1

AFAICS the code should do what you expect. To mitigate the issue you could move the inner if statement inside the try block. I'd also move the disconnect statements to a finally block.

if($VM -eq "Yes") {
    Add-PSSnapin VMware.VimAutomation.Core
    Connect-VIServer -Server $VMHost -User $VMUser -Password $VMPassword
    $Snapshot = $null
    Try {
        $Snapshot = New-Snapshot -Name $NameofSnapshot -VM $ServerName -Memory
        $CurrentPatchingState = "1;$Servername;Status=1;$(Get-Date -format 'dd.MM.yyyy hh:mm:ss') Created Snapshot" | Out-File -Filepath  "C:\$Servername.txt" -Append -encoding ASCII 
        if ($Snapshot -eq $null) {
            $CurrentPatchingState = "2;$Servername;Status=2;$(Get-Date -format 'dd.MM.yyyy hh:mm:ss') Wasnt able to get a Clean Snapshot - Aborting" | Out-File -Filepath  "C:\$Servername.txt" -Append -encoding ASCII 
            exit
        }
    } Catch [system.exception] {
        $CurrentPatchingState = "2;$Servername;Status=2;$(Get-Date -format 'dd.MM.yyyy hh:mm:ss') Wasnt able to take a Snapshot - Aborting" | Out-File -Filepath  "C:\$Servername.txt" -Append -encoding ASCII 
        exit
    } finally {
        Disconnect-VIServer -Server $VMHost -Confirm:$false
    }
}
Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
  • 1
    true that would migrate the issue. My problem with the solution is that i want to be defently sure that the Script exits if something goes wrong here, going this route wouldt it be even more possible that the script continues on (since the catch exit didnt work before)? luckily for me the if exited the script, otherwise i would have done alot of stuff without having a snapshot to recover from any errors occuring on the server. It just scares me that the if block got even touched – Ceuse Jan 19 '15 at 09:19
  • 1
    An idea a colleuge brought up. It might have been the case, that the disconnect VIServer has thrown an exception (server was not reachable for roughly 20 seconds). So the Disconnect-Vi Server might have produced an Error and the Erroractionpreference was not set. so it exited the Catch block with a not terminal error and skipped the exit. then went on and (sucsessfully) disconnected the Vi Server in the if block and then exited. Does this sound reasonable? – Ceuse Jan 19 '15 at 10:30
  • @Ceuse Hmm... if `Disconnect-VIServer` caused a terminating error while the error action was set to `SilentlyContinue`, that would explain the observed behavior. The suggested changes should mitigate that. – Ansgar Wiechers Jan 19 '15 at 12:45
  • I will mark this as the Answer, and just hope it will never happen again. Although i only added the finaly block and kept the if statement outside the try block. – Ceuse Jan 19 '15 at 15:12
0

Try this :

    Try {
            $Snapshot = New-Snapshot -Name $NameofSnapshot -VM $ServerName -Memory -ErrorAction Stop
            $CurrentPatchingState = "1;$Servername;Status=1;$(Get-Date -format 'dd.MM.yyyy hh:mm:ss') Created Snapshot" | Out-File -Filepath  "C:\$Servername.txt" -Append -encoding ASCII 
        }
Catch {
            $CurrentPatchingState = "2;$Servername;Status=2;$(Get-Date -format 'dd.MM.yyyy hh:mm:ss') Wasnt able to take a Snapshot - Aborting" | Out-File -Filepath  "C:\$Servername.txt" -Append -encoding ASCII 
            Disconnect-VIServer -Server $VMHost -Confirm:$false
            exit
        }

A Catch block is executed only if terminating error occurred in the Try block. Adding "-ErrorAction Stop" makes sure that any error during the snapshot creation will be considered as a terminating error.

Secondly, remove the "[system.exception]" at the beginning of the Catch block. This makes sure that the Catch block will apply to any type of exception.

Mathieu Buisson
  • 1,325
  • 10
  • 8