Powershell“;退出“;表现得不像应有的那样

Powershell“;退出“;表现得不像应有的那样,powershell,exception-handling,exit,Powershell,Exception Handling,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

今天我的一个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
    }
}

既然脚本应该在第一次捕获时停止,那么这怎么可能发生呢?

AFAICS代码应该按照您的预期执行。要缓解此问题,可以将内部
if
语句移动到
try
块中。我还将disconnect语句移动到
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
    }
}
if($VM-eq“Yes”){
在VMware.VimAutomation.Core中添加PSSnapin
连接VIServer-服务器$VMHost-用户$VMUser-密码$VMPassword
$Snapshot=$null
试一试{
$Snapshot=newsnapshot-Name$NameofSnapshot-VM$ServerName-Memory
$CurrentPatchingState=“1;$Servername;Status=1;$(获取日期-格式'dd.MM.yyyy hh:MM:ss')创建快照“| Out File-Filepath”C:\$Servername.txt”-追加-编码ASCII
如果($Snapshot-eq$null){
$CurrentPatchingState=“2;$Servername;Status=2;$(获取日期-格式'dd.MM.yyyy hh:MM:ss')无法获取干净的快照-中止“| Out File-Filepath”C:\$Servername.txt”-追加-编码ASCII
出口
}
}Catch[系统异常]{
$CurrentPatchingState=“2;$Servername;Status=2;$(获取日期-格式'dd.MM.yyyy hh:MM:ss')无法拍摄快照-中止“| Out File-Filepath”C:\$Servername.txt”-追加-编码ASCII
出口
}最后{
断开VIServer-服务器$VMHost-确认:$false
}
}
试试这个:

    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
        }
只有在Try块中发生终止错误时,才会执行Catch块。 添加“-ErrorAction Stop”可确保快照创建过程中的任何错误都将被视为终止错误


其次,删除Catch块开头的“[system.exception]”。这确保Catch块将应用于任何类型的异常。

您应该在try bloc中使用break,exit不是powershell关键字。请参阅相关帖子:可能重复的可能我没有说得足够清楚,我希望hole脚本停止这就是我使用Exit的原因:这将“退出”当前运行的上下文。如果从脚本调用此命令,它将退出脚本。脚本终止,但在第二个出口处而不是第一个出口处。该出口位于
[scriptblock]
内,这是它自己的上下文
出口
将该脚本块“提前”离开并返回到父上下文,脚本本身。。。第二个出口位于脚本上下文中,因此正确终止。如果为true,则会迁移问题。我的解决方案的问题是,我想防御性地确保脚本退出,如果这里出现问题,那么沿着这条路线走,脚本继续运行的可能性会更大吗(因为catch退出以前不起作用)?幸运的是,if退出了脚本,否则我将在没有快照的情况下完成很多工作,以从服务器上发生的任何错误中恢复。让我害怕的是,if block竟然被一个大学生提出的想法触动了。可能是断开连接的VIServer引发了异常(服务器在大约20秒钟内无法访问)。因此,Disconnect Vi服务器可能已产生错误,并且未设置Erroractionpreference。因此,它退出Catch块时出现了一个not-terminal错误,并跳过了退出。然后继续并(成功地)断开if块中的Vi服务器,然后退出。这听起来合理吗?@Ceuse-Hmm。。。如果
Disconnect VIServer
在错误操作设置为
SilentlyContinue
时导致终止错误,这将解释观察到的行为。建议的改变应该可以缓解这种情况。我将把这作为答案,只希望这种情况不会再次发生。尽管我只添加了finaly块,并将if语句保留在try块之外。
    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
        }