Try/catch, похоже, не имеет эффекта
Я новичок в powershell, и я пытаюсь добавить обработку ошибок с помощью операторов try/catch, но они, похоже, на самом деле не ловят ошибку. Это PowerShell версии 2 СП3.
$objComputer = $objResult.Properties;
$strComputerName = $objComputer.name
write-host "Checking machine: " $strComputerName
try
{
$colItems = get-wmiobject -class "Win32_PhysicalMemory" -namespace "rootCIMV2" -computername $strComputerName -Credential $credentials
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
}
}
Catch
{
write-host "Failed to get data from machine (Error:" $_.Exception.Message ")"
write-host
}
finally
{ }
когда он не может связаться с конкретной машиной, я получаю это в консоли, а не мое сообщение clean catch:
Get-WmiObject : The RPC server is
unavailable. (Exception from HRESULT:
0x800706BA) At Z:.0 Intern
ProgramvarePowershellGet memory of
all computers in AD.ps1:25 char:34
+ $colItems = get-wmiobject <<<< -class "Win32_PhysicalMemory"
-namespace "rootCIMV2" -computername $strComputerName -Credential
$credentials
+ CategoryInfo : InvalidOperation: (:) [Get-WmiObject],
COMException
+ FullyQualifiedErrorId : GetWMICOMException,Microsoft.PowerShell.Commands.GetWmiObjectCommand
6 ответов:
мне удалось скопировать ваш результат при попытке запустить удаленный запрос WMI. Брошенное исключение не поймано Try/Catch, и ловушка не поймает его, так как это не "завершающая ошибка". В 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, которая принимает scriptblocks, чтобы ваши вызовы 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"; }
также можно задать параметр действия ошибки для отдельных командлетов, а не только для всего сценария. Это делается с помощью параметра 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 не остановить это самый простой способ решения этой проблемы.
try { Set-Location "$YourPath" -ErrorAction Stop; } catch { Write-Host "Exception has been caught"; }
Edit: как указано в комментариях, следующее решение применяется только к PowerShell V1.
посмотреть это сообщение в блоге на тему "технические приключения Адама Вайгерта" подробнее о том, как реализовать это.
пример использования (копировать / вставить из блога Адама Вайгерта):
Try { echo " ::Do some work..." echo " ::Try divide by zero: $(0/0)" } -Catch { echo " ::Cannot handle the error (will rethrow): $_" #throw $_ } -Finally { echo " ::Cleanup resources..." }в противном случае вам придется использовать исключения запутывания.
Comments