Private/Wissen/C_Advance/C04_Error.ps1
<#
# Error Fehler/Exception unterdrücken, analysieren, behandeln oder auslösen - **Hashtags** ErrorRecord Exception $error trap try catch finally - **Version** 2020.01.23 #> [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingEmptyCatchBlock', '')] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')] 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 .\AKPT\Private\Wissen\C_Scripting\C04_Debugging.ps1 #region Neuerungen der PowerShell 7 # ! Standard-Fehlerausgabe-Menge über $ErrorView bestimmen Get-help -Name ABOUT_PREFERENCE_VARIABLES -ShowWindow $ErrorView = [System.Management.Automation.ErrorView]::NormalView # ! Umfassende Fehler-Ausgabe 1/0 # * Fehler provozieren! $ErrorView = [System.Management.Automation.ErrorView]::ConciseView # ! DEFAULT: Fehler-Ausgabe enthält nur eine Kurzfassung 1/0 # * Fehler provozieren! $ErrorView = [System.Management.Automation.ErrorView]::CategoryView # ! Nur Fehler-Ausgabe enthält nur die Kategorie 1/0 # * Fehler provozieren! # ! Wird der ErrorAction der neue Wert 'Break' zugewiesen, hält die Ausführung an und es wird den DEBUG-Modus gewechselt $ErrorActionPreference = [System.Management.Automation.ActionPreference]::Break Get-Process -FileVersionInfo -ErrorAction Break # ! Die letzten Fehler auswerten mit dem neuen Cmdlet 'Get-Error': Get-Process -FileVersionInfo # * Fehler provozieren! Get-Error Get-Error -Newest 1 #endregion #region Meldungen u.a. unterdrücken # ? Lokal Unterdrückung: Get-Process -FileVersionInfo -ErrorAction 'Stop' -WarningAction 'Ignore' -InformationAction 'Continue' -Verbose # ! Mögliche Werte sind: [System.Management.Automation.ActionPreference]::Continue [System.Management.Automation.ActionPreference]::Ignore [System.Management.Automation.ActionPreference]::Inquire [System.Management.Automation.ActionPreference]::SilentlyContinue [System.Management.Automation.ActionPreference]::Stop [System.Management.Automation.ActionPreference]::Suspend # ? Globale Unterdrückung: $ErrorActionPreference = [System.Management.Automation.ActionPreference]::Stop # ! Default => Continue TIPP: In .PS1-Dateien im Kopfbereich auf Stop setzen! $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 # ? Beispiel A: 1/0 $Error[0] # Ist immer der letzte Fehler $Error[0] | Get-ErrorInfo # ! ACHTUNG nur im AKPT-Modul oder PowerShell 7 mit Get-Error s.o. # ? Beispiel B: $myErrors = @() Get-Process -FileVersionInfo -ErrorVariable 'myErrors' "Aufgetretene Fehler: $($myErrors.Count)" $myErrors[0] | Get-ErrorInfo # ! ACHTUNG nur im AKPT-Modul oder PowerShell 7 mit Get-Error s.o. # ? Beispiel C: $myErrors = @() Get-Content -Path 'C:\MichGibtEsNicht.txt' -ErrorVariable 'myErrors' "Aufgetretene Fehler: $($myErrors.Count)" $myErrors | Get-ErrorInfo # ! ACHTUNG nur im AKPT-Modul oder PowerShell 7 mit Get-Error s.o. #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 Spooler -Force if ($?) { "'Stop-Service -Name Spooler -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 $_.Message 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' break } 12/0 Get-Content -Path C:\MichGibtEsNicht.txt Get-Process -Name wininit -FileVersionInfo $ErrorActionPreference = $ErrorActionPreferenceBackup #endregion #endregion #region Eigene Fehler auslösen # ? Native PowerShell Fehler (RuntimeException) 1/0 # ? ... durch Typenfestlegung [byte]$Hubraum = 5000 [System.Net.Mail.MailAddress]$ToEmail = 'Attila Krick<info@attilakrick.com>' # ? ... durch Write-Error 'UPS, da hat etwas nicht geklappt (ErrorCode: 4711)' | Write-Error # ? ... durch div. Validate-Attributen für eigen Cmdlet-Parameter [ValidateRange(5, 10)]$Hubraum = 6 $Hubraum = 11 [ValidatePattern('^[a-z]{2,5}[0-9]+')]$HostName = 'abc2' $HostName = 'ab1' # ? ... 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 einer 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 $this.KundeId = $kundeId } } throw New-Object -TypeName KundeVorhandenException -ArgumentList "Der Kunde ist bereits vorhanden", 4711 #endregion #region Übungen # TIPPS: Get-ErrorDetails; $error # 1. Welche Werte kann die `$ErrorActionPreference`-Variable aufnehmen, welche Bedeutung haben diese Werte und wie sind Sie auf diese Werte/Informationen gekommen? # 2. Welche Exception werden von den folgenden Code-Zeilen ausgelöst? Get-Process -Name Haeckihaeckipateng # 3. Welche Exception werden von den folgenden Code-Zeilen ausgelöst? 100 / $xyz # 4. Welche Exception wird von folgender Code-Zeile ausgelöst? [datetime]'31.12.2019' # 5. Welche Exception werden von den folgenden Code-Zeilen ausgelöst? Invoke-WebRequest -Uri 'http:\\www.gfu.net\Seminare.html' #endregion |