尝试运行远程WMI查询时,我能够复制您的结果.抛出的异常不是由Try/Catch捕获的,Trap也不会捕获它,因为它不是"终止错误".在PowerShell中,存在终止错误和非终止错误.似乎Try/Catch/Finally和Trap仅适用于终止错误.
它被记录到$ error自动变量,您可以通过查看$来测试这些类型的非终止错误?自动变量,它会让你知道最后一次操作是成功($ true)还是失败($ false).
从生成的错误的外观,似乎返回错误,而不是包含在可捕获的异常中.下面是生成的错误的痕迹.
PS C:\scripts\PowerShell> Trace-Command -Name errorrecord -Expression {Get-WmiObject win32_bios -ComputerName HostThatIsNotThere} -PSHost DEBUG: InternalCommand Information: 0 : Constructor Enter Ctor Microsoft.PowerShell.Commands.GetWmiObjectCommand: 25857563 DEBUG: InternalCommand Information: 0 : Constructor Leave Ctor Microsoft.PowerShell.Commands.GetWmiObjectCommand: 25857563 DEBUG: ErrorRecord Information: 0 : Constructor Enter Ctor System.Management.Automation.ErrorRecord: 19621801 exception = System.Runtime.InteropServices.COMException (0x800706BA): The RPC server is unavailable. (Exception from HRESULT: 0x800706BA) at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo) at System.Management.ManagementScope.InitializeGuts(Object o) at System.Management.ManagementScope.Initialize() at System.Management.ManagementObjectSearcher.Initialize() at System.Management.ManagementObjectSearcher.Get() at Microsoft.PowerShell.Commands.GetWmiObjectCommand.BeginProcessing() errorId = GetWMICOMException errorCategory = InvalidOperation targetObject = DEBUG: ErrorRecord Information: 0 : Constructor Leave Ctor System.Management.Automation.ErrorRecord: 19621801
解决代码的方法可能是:
try { $colItems = get-wmiobject -class "Win32_PhysicalMemory" -namespace "root\CIMV2" -computername $strComputerName -Credential $credentials if ($?) { foreach ($objItem in $colItems) { write-host "Bank Label: " $objItem.BankLabel write-host "Capacity: " ($objItem.Capacity / 1024 / 1024) write-host "Caption: " $objItem.Caption write-host "Creation Class Name: " $objItem.CreationClassName write-host } } else { throw $error[0].Exception }
如果您希望try/catch适用于所有错误(而不仅仅是终止错误),您可以通过设置ErrorActionPreference手动使所有错误终止.
try { $ErrorActionPreference = "Stop"; #Make all errors terminating get-item filethatdoesntexist; # normally non-terminating write-host "You won't hit me"; } catch{ Write-Host "Caught the exception"; Write-Host $Error[0].Exception; }finally{ $ErrorActionPreference = "Continue"; #Reset the error action pref to default }
或者......您可以创建自己的trycatch函数来接受脚本块,这样您的try catch调用就不会像kludge一样.我有我的返回true/false,以防我需要检查是否有错误...但它不必.此外,异常日志记录是可选的,并且可以在catch中处理,但我发现自己总是在catch块中调用日志记录函数,所以我将它添加到try catch函数中.
function log([System.String] $text){write-host $text;} function logException{ log "Logging current exception."; log $Error[0].Exception; } function mytrycatch ([System.Management.Automation.ScriptBlock] $try, [System.Management.Automation.ScriptBlock] $catch, [System.Management.Automation.ScriptBlock] $finally = $({})){ # Make all errors terminating exceptions. $ErrorActionPreference = "Stop"; # Set the trap trap [System.Exception]{ # Log the exception. logException; # Execute the catch statement & $catch; # Execute the finally statement & $finally # There was an exception, return false return $false; } # Execute the scriptblock & $try; # Execute the finally statement & $finally # The following statement was hit.. so there were no errors with the scriptblock return $true; } #execute your own try catch mytrycatch { gi filethatdoesnotexist; #normally non-terminating write-host "You won't hit me." } { Write-Host "Caught the exception"; }
也可以在单个cmdlet上设置错误操作首选项,而不仅仅是整个脚本.这是使用所有cmdlet上都可用的参数ErrorAction(alisa EA)完成的.
例
try { Write-Host $ErrorActionPreference; #Check setting for ErrorAction - the default is normally Continue get-item filethatdoesntexist; # Normally generates non-terminating exception so not caught write-host "You will hit me as exception from line above is non-terminating"; get-item filethatdoesntexist -ErrorAction Stop; #Now ErrorAction parameter with value Stop causes exception to be caught write-host "you won't reach me as exception is now caught"; } catch { Write-Host "Caught the exception"; Write-Host $Error[0].Exception; }
这是我的解决方案。当Set-Location失败时,它将引发一个非终止错误,catch块不会看到该错误。添加-ErrorAction Stop是解决此问题的最简单方法。
try { Set-Location "$YourPath" -ErrorAction Stop; } catch { Write-Host "Exception has been caught"; }