PowerShell/03core11 min

Obsługa błędów (try/catch, $ErrorActionPreference)

Probe ZEUS działa na zdalnej maszynie klienta — gdy coś pójdzie nie tak, backend musi dostać czytelny błąd, a nie zawieszony proces albo pusty JSON. Klucz do tego to zrozumienie błędów terminujących i poprawne try/catch.

Dwa rodzaje błędów

PowerShell rozróżnia błędy nieterminujące (skrypt leci dalej) i terminujące (przerywają wykonanie). try/catch łapie tylko terminujące — i to jest pułapka.

# błąd nieterminujący — try/catch go NIE złapie
try {
    Get-ADUser -Identity "nieistnieje"   # zwykły błąd, leci dalej
} catch {
    Write-Host "Tu nie wejdzie"
}

$ErrorActionPreference i -ErrorAction

Żeby try/catch zadziałał, błąd musi być terminujący. Wymuszamy to przez -ErrorAction Stop na poziomie polecenia.

try {
    Get-ADUser -Identity "nieistnieje" -ErrorAction Stop
} catch {
    Write-Verbose "Nie znaleziono użytkownika: $($_.Exception.Message)"
}

Globalnie ustawiamy to na początku skryptu:

$ErrorActionPreference = "Stop"

Standard ProfessNet: skrypty probe zaczynają od $ErrorActionPreference = "Stop". Wtedy każdy błąd jest terminujący i wpada w try/catch — żaden problem nie przechodzi po cichu.

Wzorzec probe: catch zwraca błąd jako JSON

W probe'ach ZEUS catch nie tylko loguje — buduje ustrukturyzowany obiekt błędu i wypisuje go na stdout jako JSON, żeby backend mógł go sparsować.

[CmdletBinding()]
param([Parameter(Mandatory)][string]$Forest, [switch]$AsJson)

$ErrorActionPreference = "Stop"

try {
    $forest = Get-ADForest -Identity $Forest
    $result = [pscustomobject]@{
        Ok      = $true
        Forest  = $forest.Name
        Domains = $forest.Domains
    }
}
catch {
    $result = [pscustomobject]@{
        Ok    = $false
        Error = $_.Exception.Message
        Type  = $_.Exception.GetType().Name
    }
}

if ($AsJson) {
    $result | ConvertTo-Json -Depth 5 -Compress
}

Standard ProfessNet: probe zawsze zwraca ustrukturyzowany wynik — sukces albo błąd jako JSON na stdout. Niezłapany wyjątek = zepsuty kontrakt z backendem.

Informacje o błędzie

Obiekt błędu ($_ w catch, $Error[0] globalnie) niesie pełny kontekst:

catch {
    $_.Exception.Message                       # treść błędu
    $_.Exception.GetType().FullName            # typ wyjątku
    $_.InvocationInfo.ScriptLineNumber         # gdzie wystąpił
    $_.ScriptStackTrace                        # pełny stos
}

finally — sprzątanie

finally wykonuje się zawsze, niezależnie od błędu — do zwalniania sesji, zamykania połączeń.

$session = New-PSSession -ComputerName $target
try {
    Invoke-Command -Session $session -ScriptBlock { Get-Service }
}
finally {
    Remove-PSSession $session    # sesja zamknięta nawet przy błędzie
}
ElementRola
$ErrorActionPreference = "Stop"wszystkie błędy terminujące
-ErrorAction Stopwymusza terminację dla jednego polecenia
try/catchprzechwytuje błąd terminujący
finallysprzątanie zawsze (sesje, połączenia)

Wskazówka: nie używaj throw bez wiadomości. Rzucaj sensowny komunikat: throw "Forest $Forest niedostępny: $($_.Exception.Message)".


$ErrorActionPreference = "Stop", try/catch z błędem zwracanym jako JSON i finally do sprzątania — to fundament niezawodnego probe'a. Backend dostaje zawsze czytelny wynik, nigdy ciszę.