usar tutorial script como commands comandos powershell

powershell - tutorial - Try/catch no parece tener un efecto



powershell tutorial (6)

Agregar "-EA Stop" resolvió esto para mí.

Soy nuevo en powershell, y estoy tratando de agregar el manejo de errores a través de declaraciones try / catch, pero parece que en realidad no captan el error. Esto es powershell v2 CP3.

$objComputer = $objResult.Properties; $strComputerName = $objComputer.name write-host "Checking machine: " $strComputerName try { $colItems = get-wmiobject -class "Win32_PhysicalMemory" -namespace "root/CIMV2" -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 { }

Cuando falla en contactar una máquina específica, la recibo en la consola, y no en mi mensaje de captura limpia:

Get-WmiObject : The RPC server is
unavailable. (Exception from HRESULT:
0x800706BA) At Z:/7.0 Intern
Programvare/Powershell/Get memory of
all computers in AD.ps1:25 char:34
+ $colItems = get-wmiobject <<<< -class "Win32_PhysicalMemory"
-namespace "root/CIMV2" -computername $strComputerName -Credential
$credentials
+ CategoryInfo : InvalidOperation: (:) [Get-WmiObject],
COMException
+ FullyQualifiedErrorId : GetWMICOMException,Microsoft.PowerShell.Commands.GetWmiObjectCommand


Esta es mi solución. Cuando Set-Location falla, arroja un error que no termina y que no es visto por el bloque catch. Agregar -ErrorAction Stop es la forma más fácil de evitar esto.

try { Set-Location "$YourPath" -ErrorAction Stop; } catch { Write-Host "Exception has been caught"; }


Pude duplicar tu resultado al intentar ejecutar una consulta WMI remota. La excepción lanzada no es capturada por Try / Catch, ni una trampa la atrapará, ya que no es un "error de terminación". En PowerShell, hay errores de terminación y no terminantes. Parece que Try / Catch / Finally y Trap solo funcionan con errores de terminación.

Está registrado en la variable automática de $ error y puede probar este tipo de errores que no terminan mirando los $? variable automática, que le permitirá saber si la última operación tuvo éxito ($ true) o falló ($ false).

A partir de la aparición del error generado, parece que el error se devuelve y no se envuelve en una excepción atrapable. A continuación se muestra un rastro del error generado.

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

Un trabajo para su código podría ser:

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 }


Si desea que try / catch funcione para todos los errores (no solo para los errores de terminación), puede finalizar manualmente todos los errores configurando 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 }

Alternativamente ... puede hacer su propia función catchcatch que acepte scriptblocks para que sus try catch calls no sean tan kludge. Tengo el mío verdadero / falso en caso de que necesite verificar si hubo un error ... pero no tiene que ser así. Además, el registro de excepciones es opcional, y se puede tener en cuenta en la captura, pero siempre me encontré llamando a la función de registro en el bloque catch, así que lo agregué a la función 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"; }


También es posible establecer la preferencia de acción de error en cmdlets individuales, no solo para todo el script. Esto se hace usando el parámetro ErrorAction (alisa EA) que está disponible en todos los cmdlets.

Ejemplo

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; }


Editar: como se indica en los comentarios, la siguiente solución se aplica solo a PowerShell V1.

Vea esta publicación en el blog sobre "Aventuras técnicas de Adam Weigert" para obtener detalles sobre cómo implementar esto.

Ejemplo de uso (copiar / pegar desde el blog de Adam Weigert):

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..." }

De lo contrario, tendrá que usar la captura de excepciones .