在PowerShell脚本中,Try Catch无法正常工作

19

我似乎无法让这个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

}

可能是try/catch似乎没有效果的重复问题。 - Michael Freidgeim
4个回答

49

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

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
}

21

1)你的catch语句有一个拼写错误。它应该为Write-Host

2)在PowerShell中进行try-catch与大多数其他编程语言不同。 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 中使用。 - js2010
我不得不在我的脚本中给“Stop”一词加上引号,否则该命令将无法正常工作:$ErrorActionPreference = "Stop"。 - Marc Levesque

1
我稍微修改了你的函数参数,但是对于你的回答,我必须说,由于你使用了“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

}

希望它有所帮助。

1

与其使用 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] }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接