Powershell Exit ведет себя не так, как должен

Сегодня у меня возникла странная проблема в одном из моих сценариев PowerShell:

Информация об окружающей среде: сценарий PowerShell, о котором я говорю, вызывается 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
    }
}

Сегодня сценарий провалился в этой части. Файл журнала показал:

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

Как это могло произойти, ведь скрипт должен был остановиться на первом же улове?


person Ceuse    schedule 19.01.2015    source источник
comment
Вы должны использовать break в блоке try, exit не является ключевым словом powershell. См. Соответствующий пост: stackoverflow.com/a/23703056/381149   -  person Loïc MICHEL    schedule 19.01.2015
comment
возможный дубликат завершения сценария в PowerShell   -  person Loïc MICHEL    schedule 19.01.2015
comment
возможно, я недостаточно ясно выразился, я хотел, чтобы скрипт дыры остановился, поэтому я использовал Exit: это приведет к выходу из текущего текущего контекста. Если вы вызовете эту команду из сценария, он выйдет из сценария. Скрипт прерван, но при втором выходе не на первом.   -  person Ceuse    schedule 19.01.2015
comment
Выход находится в [scriptblock], который является его собственным контекстом, exit оставил этот блок сценария «раньше» и вернулся в родительский контекст, сам сценарий ... 2-й выход находится в контексте сценария и поэтому завершается правильно.   -  person Djarid    schedule 15.04.2016


Ответы (2)


AFAICS код должен делать то, что вы ожидаете. Чтобы смягчить проблему, вы можете переместить внутренний оператор if внутрь блока try. Я бы также переместил операторы отключения в блок finally.

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
    }
}
person Ansgar Wiechers    schedule 19.01.2015
comment
правда, что перенесет проблему. Моя проблема с решением заключается в том, что я хочу быть уверенно уверенным, что сценарий завершится, если здесь что-то пойдет не так, при переходе по этому маршруту было бы еще более вероятно, что сценарий продолжится (поскольку выход catch не работал раньше)? К счастью для меня, if вышел из сценария, иначе я бы сделал много вещей, не имея моментального снимка для восстановления после любых ошибок, возникающих на сервере. Меня просто пугает, что блок if даже коснулся - person Ceuse; 19.01.2015
comment
Идея, которую подал коллега. Возможно, отключившийся VIServer вызвал исключение (сервер был недоступен в течение примерно 20 секунд). Таким образом, сервер Disconnect-Vi мог выдать ошибку, а предпочтение Erroraction не было установлено. поэтому он вышел из блока Catch с нетерминальной ошибкой и пропустил выход. затем продолжил и (успешно) отключил Vi Server в блоке if и затем вышел. Это звучит разумно? - person Ceuse; 19.01.2015
comment
@Ceuse Хм ... если Disconnect-VIServer вызвал завершающую ошибку, в то время как действие при ошибке было установлено на SilentlyContinue, это объяснило бы наблюдаемое поведение. Предлагаемые изменения должны смягчить это. - person Ansgar Wiechers; 19.01.2015
comment
Я отмечу это как Ответ и надеюсь, что это больше никогда не повторится. Хотя я добавил только финальный блок и сохранил оператор if за пределами блока try. - person Ceuse; 19.01.2015

Попробуй это :

    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
        }

Блок Catch выполняется только в том случае, если в блоке Try возникла завершающая ошибка. Добавление «-ErrorAction Stop» гарантирует, что любая ошибка во время создания моментального снимка будет считаться прерывающей ошибкой.

Во-вторых, удалите «[system.exception]» в начале блока Catch. Это гарантирует, что блок Catch будет применяться к любому типу исключения.

person Mathieu Buisson    schedule 19.01.2015