【问题标题】:Try Catch not working in Powershell Script尝试 Catch 在 Powershell 脚本中不起作用
【发布时间】:2017-01-05 02:42:02
【问题描述】:

我似乎无法让这个 try-catch 工作。我敢肯定这很简单,但此刻我的大脑实在是太煎熬了。请帮忙!

param(
[String[]]$RemoteServicesVMs = ('VmThatThrowsError')
)

function getWinServiceStatus
{

#Get-WmiObject "win32_service" 
    try{

        Get-WmiObject "win32_service" | Where-Object {$_.startname -notlike "NT*" -and $_.startname -notlike "local*" } | Format-Table -property PSComputerName, name, state, status, startname

    }  
    catch{

        wite-host "Failed"

    }

}

$PassWordEnc = convertto-securestring $RemotePassWord -asplaintext -force
$MyCred = New-Object -TypeName System.Management.Automation.PSCredential ArgumentList $RemoteUserName,$PassWordEnc

foreach($RemoteServicesVM in $RemoteServicesVMs){

    Invoke-Command -ComputerName $RemoteServicesVM -Port 5985 -Authentication Negotiate -ScriptBlock ${function:getWinServiceStatus} -Credential $MyCred

}

【问题讨论】:

标签: powershell try-catch


【解决方案1】:

Try/Catch 只会在终止异常时“触发”。默认情况下,PowerShell 中的大多数 cmdlet 不会引发终止异常。您可以使用-ErrorAction 或-ea 参数设置错误操作:

Do-Thing 'Stuff' -ErrorAction Stop

这么说...我认为Get-WmiObject 不会产生终止错误。如果它没有找到任何东西,它就不会返回任何东西。在这种情况下,您可以在 try 块中有一个 if 条件,然后手动抛出:

Try {
    $Obj = Get-WmiObject "win32_service" | Where ...
    if ($null -eq $Obj) {
        throw
    }
}
Catch {
    # Error Handling
}

【讨论】:

    【解决方案2】:

    1) 您的 catch 语句有错字。应该是Write-Host

    2) Powershell 中的尝试捕获与大多数其他编程语言不同。 Powershell中有两种类型的错误,终止和非终止。默认情况下,非终止错误不会触发您的 catch 处理。

    因此,如果您想强制 powershell 捕捉错误,无论它是什么类型,您都可以将-ErrorAction Stop 附加到您的InvokeCommand 行。

    例如:

    Invoke-Command -ComputerName $RemoteServicesVM -Port 5985 -Authentication Negotiate -ScriptBlock ${function:getWinServiceStatus} -Credential $MyCred -ErrorAction Stop
    

    或者(从下面的链接复制):

    也可以使用 ErrorActionPreference 变量将所有错误视为终止。您可以为正在使用的脚本或整个 PowerShell 会话执行此操作。要在脚本中设置它,使第一行 $ErrorActionPreference = Stop。要为会话设置它,请在 PowerShell 控制台中键入 $ErrorActionPreference = Stop。

    在此处查看更多信息:http://www.vexasoft.com/blogs/powershell/7255220-powershell-tutorial-try-catch-finally-and-error-handling-in-powershell

    【讨论】:

    • 实际上有两种终止错误。一种会结束整个脚本,而另一种不会,但仍然可以在 try/catch 中使用。
    • 我必须在脚本中的 stop 一词周围加上引号,否则命令将不起作用:$ErrorActionPreference = "Stop"
    【解决方案3】:

    我稍微修改了你的函数参数,但是对于你的答案,我不得不说,因为你使用的是 notlike 你的 get-wmiobject 没有返回任何错误。

    如果数据也不存在,它会显示为空白。您可以通过将输出放入变量并显示输出来缩小问题范围。

    你应该使用带有通配符的-eq来处理它。

    要缩小问题范围,请使用:

    $erroractionpreference = stop;
    function getWinServiceStatusparam(
    [String[]]$RemoteServicesVMs = ('VmThatThrowsError')
    )
    {
    
    #Get-WmiObject "win32_service" 
        try{
    
           $a=  Get-WmiObject "win32_service" | Where-Object {$_.startname -notlike "NT*" -and $_.startname -notlike "local*" } | Format-Table -property PSComputerName, name, state, status, startname
           Write-Host $a
        }  
        catch{
    
            wite-host "Failed"
    
        }
    
    }
    
    $PassWordEnc = convertto-securestring $RemotePassWord -asplaintext -force
    $MyCred = New-Object -TypeName System.Management.Automation.PSCredential ArgumentList $RemoteUserName,$PassWordEnc
    
    foreach($RemoteServicesVM in $RemoteServicesVMs){
    
        Invoke-Command -ComputerName $RemoteServicesVM -Port 5985 -Authentication Negotiate -ScriptBlock ${function:getWinServiceStatus} -Credential $MyCred
    
    }
    

    希望对你有帮助。

    【讨论】:

      【解决方案4】:

      您可以检查最后一个命令是否成功运行,然后处理它,而不是 try/catch:

      Get-WmiObject "win32_service"
      if(!$?){
        if($error[0].exception.message -match "invalid class"){ write-warning "The class doesn't exist"}
        else{ throw $error[0] }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-11-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-08-26
        相关资源
        最近更新 更多