Private/Wissen/C05_Error.ps1
# ? TITEL Error # ? DESCRIPTION Fehler/Exception unterdrücken, analysieren, behandeln oder auslösen # ? TAGS ErrorRecord Exception $error trap try catch finally # ? VERSION 2019.10.13 [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingEmptyCatchBlock', '')] param() # TODO Weiterführende und Nachschlage-Informationen Get-Help -Name about_Try_Catch_Finally -ShowWindow Get-Help -Name about_Trap -ShowWindow Get-Help -Name about_Throw -ShowWindow # * Siehe Thema *_Debugging.ps1 #region Meldungen u.a. unterdrücken # ? Lokal Unterdrückung: Get-Process -FileVersionInfo -ErrorAction Stop -WarningAction Ignore -InformationAction Continue -Verbose # ? Globale Unterdrückung: $ErrorActionPreference = [System.Management.Automation.ActionPreference]::Stop # ! Default => Continue $WarningPreference = [System.Management.Automation.ActionPreference]::Stop # ! Default => Continue $InformationPreference = [System.Management.Automation.ActionPreference]::Stop # ! Default => SilentlyContinue $VerbosePreference = [System.Management.Automation.ActionPreference]::Stop # ! Default => SilentlyContinue Get-Process #region Unterdrückung in eigenen Cmdlets einbauen function Test-CommonParameter { [CmdletBinding()] # ! WICHTIG um die Common-Parameters nutzen zu können param ( ) "Error Test" | Write-Error "Warning Test" | Write-Warning "Verbose test" | Write-Verbose Write-Information -MessageData "Information Test" "Debug Test" | Write-Debug } Test-CommonParameter Test-CommonParameter -ErrorAction SilentlyContinue -WarningAction Ignore -Verbose -InformationAction Continue Test-CommonParameter -Debug #endregion #endregion #region Fehler analysieren # ! Hilfreiches Cmdlet zur Analyse von Fehler: filter Get-ErrorDetails { $Category = @{ Name = 'CategoryInfo' ; Expression = { $_.CategoryInfo.Category }} $Line = @{ Name = 'LineNumber' ; Expression = { $_.InvocationInfo.ScriptLineNumber }} $Script = @{ Name = 'ScriptName' ; Expression = { $_.InvocationInfo.ScriptName }} $Target = @{ Name = 'Target' ; Expression = { $_.TargetObject }} $ErrorId = @{ Name = 'ErrorId' ; Expression = { $_.FullyQualifiedErrorID }} $ExType = @{ Name = 'ExceptionType' ; Expression = { $_.Exception.GetType().FullName }} $ExMessage = @{ Name = 'ExceptionMessage' ; Expression = { $_.Exception.Message }} $ExInnerException = @{ Name = 'InnerExceptionMessage' ; Expression = { $_.Exception.InnerException }} $Input | Select-Object -Property $Category, $Line, $Script, $Target, $ErrorId, $ExType, $ExMessage, $ExInnerException } # ? Beispiel A: $myErrors = @() Get-Process -FileVersionInfo -ErrorVariable myErrors "Aufgetretene Fehler: $($myErrors.Count)" $myErrors | Get-ErrorDetails # ! auch ein hilfreiches Cmdlet, benötigt jedoch das Module PSCX (Install-Module -Name PSCX) Resolve-ErrorRecord -ErrorRecord $myErrors # ? Beispiel B: $myErrors = @() Get-Content -Path C:\MichGibtEsNicht.txt -ErrorVariable myErrors "Aufgetretene Fehler: $($myErrors.Count)" $myErrors | Get-ErrorDetails #region Die $error-Systemvariable $error # Enthält 256 Fehler seit beginn der Session $MaximumErrorCount $MaximumErrorCount = 999 # Default 256 $error.Count $error | Select-Object -Last 1 # ! Der älteste Fehler ($error[$error.Count - 1]) $error | Select-Object -First 1 # ! Der neuste Fehler ($error[0]) # ? Nutzen, z.B.: $error.Clear() 42 / 0 "Aufgetretene Fehler: $($error.Count)" $error | Get-ErrorDetails #endregion # Wurde der letzte Befehl erfolgreich ausgeführt? Stop-Service -Name Audiosrv -Force if ($?) { "'Stop-Service -Name Audiosrv -Force' wurde erfolgreich ausgeführt!" } #endregion #region Fehler behandeln #region per try, catch und finally # ! try..catch nur benutzen wenn EINE LÖSUNG implementiert wird, # ! da dieses Konstrukt der PowerShell signalisiert das der Fehler behoben wurde! # ! ####################################### # ! ### EINE MELDUNG IST KEINE LÖSUNGEN ### # ! ####################################### try { $ErrorActionPreferenceBackup = $ErrorActionPreference $ErrorActionPreference = [System.Management.Automation.ActionPreference]::Stop # ! Code der evtl. einen Fehler auslöst: Get-Content c:\temp\wichtig.txt } catch [System.Management.Automation.ItemNotFoundException] { # ! Code der diesen Fehler behebt: New-Item c:\temp\wichtig.txt } catch [System.OutOfMemoryException] { # ! Völlig spezifischer Fehler # ! Code der diesen Fehler behebt } catch [System.SystemException] { # Bereichsfehler } catch { # Völlig unspezifische Fehler # ! Code der diesen Fehler behebt => Was könnte das nur sein !?!?!? $_.GetType().FullName throw $_ } finally { $ErrorActionPreference = $ErrorActionPreferenceBackup } #endregion #region über trap $ErrorActionPreferenceBackup = $ErrorActionPreference $ErrorActionPreference = [System.Management.Automation.ActionPreference]::Stop trap [System.DivideByZeroException] { '[SIRENE] => Division durch 0 wurde festgestellt' continue } trap [System.Management.Automation.ActionPreferenceStopException] { '[SIRENE] => Eine ActionPreferenceStopException ist aufgetreten, tatsächliche Exception auslösen und abfangen' throw $_.Exception continue trap [System.Management.Automation.ItemNotFoundException] { '[SIRENE] => Die Datei wurde nicht gefunden' continue } trap { '[SIRENE] => Irgend ein anderer Fehler in ActionPreferenceStopException ist aufgetreten' continue } } trap { '[SIRENE] => Irgend ein anderer Fehler ist aufgetreten' continue } 12/0 Get-Content -Path C:\MichGibtEsNicht.txt Get-Process -Name wininit -FileVersionInfo $ErrorActionPreference = $ErrorActionPreferenceBackup #endregion #endregion #region Eigene Fehler auslösen # ? ... durch Typenfestlegung [byte]$hubraum = 5000 # ? ... durch Write-Error "UPS, da hat etwas nicht geklappt" | Write-Error # ? ... durch div. Validate-Attributen für eigen Cmdlet-Parameter [ValidateRange(5, 10)] $Hubraum = 11 # ? ... durch throw String-Text throw "Ihr Geburtsdatum muss kleiner oder gleich Heute $(Get-Date -Format dd.MM.yyyy) sein." # ? ... durch das Auslösen einer vorhanden Exception-Klasse throw New-Object -TypeName System.ArgumentException -ArgumentList "Wert 'xyz' ist ungültig.", "Geburtsdatum" # ? ... durch das Auslösen einr selbst deklarierte Exception-Klasse [System.SerializableAttribute()] class KundeVorhandenException : System.Exception { [string]$Message [int]$KundeId KundeVorhandenException([string]$message, [int]$kundeId) : base("$message (Kunde $kundeId)") { $this.Message = $message } } throw New-Object -TypeName KundeVorhandenException -ArgumentList "Der Kunde ist bereits vorhanden", 4711 #endregion #region Übungen <# TODO ÜBUNG Error Handling 1 ! VERTIEFUNG: Exception-Namen ermitteln ? Welche Exception werden von den folgenden Code-Zeilen ausgelöst? Invoke-WebRequest -Uri "http:\\www.gfu.net\Seminare.html" 100 / $xyz Get-Process -Name Haeckihaeckipateng [datetime]"31.12.2019" TIPPS: Get-ErrorDetails; Resolve-ErrorRecord; $error * LÖSUNG #> #endregion |