我似乎无法让这个 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 只会在终止异常时“触发”。默认情况下,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
}
您的 catch 语句有一个拼写错误。应该是
Write-Host
Powershell 中的尝试捕获与大多数其他编程语言不同。 Powershell 中有两种类型的错误:终止错误和非终止错误。默认情况下,非终止错误将不会触发您的 catch 处理。
因此,如果您想 force powershell 捕获错误,无论它是什么类型,您可以将
-ErrorAction Stop
附加到您的 Invoke-Command
行。
例如:
Invoke-Command -ComputerName $RemoteServicesVM -Port 5985 -Authentication Negotiate -ScriptBlock ${function:getWinServiceStatus} -Credential $MyCred -ErrorAction Stop
或者(从下面的链接复制):
也可以使用 ErrorActionPreference 变量将所有错误视为终止。您可以对正在使用的脚本或整个 PowerShell 会话执行此操作。要在脚本中设置它,请将第一行设置为 $ErrorActionPreference = Stop。要为会话设置它,请在 PowerShell 控制台中输入 $ErrorActionPreference = Stop。
我稍微修改了你的函数参数,但对于你的答案,我不得不说,因为你使用的是 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
}
希望有帮助。
您可以检查最后一个命令是否成功运行,然后处理它,而不是尝试/捕获:
Get-WmiObject "win32_service"
if(!$?){
if($error[0].exception.message -match "invalid class"){ write-warning "The class doesn't exist"}
else{ throw $error[0] }
}