about_Error_Handling

Deskripsi singkat

Menjelaskan jenis kesalahan di PowerShell dan mekanisme untuk menanganinya.

Deskripsi panjang

PowerShell membedakan tiga kategori kesalahan:

  • Kesalahan non-penghentian
  • Kesalahan penghentian pernyataan
  • Kesalahan penghentian skrip

Memahami perbedaan sangat penting untuk menulis skrip dan modul yang andal, karena setiap kategori memiliki perilaku default yang berbeda dan memerlukan teknik penanganan yang berbeda.

Selain itu, program eksternal (asli) melaporkan kegagalan melalui kode keluar, yang dilacak PowerShell secara terpisah dari sistem kesalahannya sendiri.

Jenis kesalahan

Kesalahan non-penghentian

Kesalahan yang tidak mengakhiri melaporkan masalah tetapi tidak menghentikan alur. Perintah melanjutkan pemrosesan objek input berikutnya. Kesalahan yang tidak mengakhiri dihasilkan oleh:

  • Cmdlet Write-Error
  • Metode $PSCmdlet.WriteError() dalam fungsi lanjutan
  • Cmdlet yang mengalami kegagalan yang dapat dipulihkan pada objek input individual

Secara default, PowerShell menampilkan pesan kesalahan dan melanjutkan eksekusi.

# Non-terminating error: the pipeline continues after the failure
'file1.txt', 'noSuchFile.txt', 'file3.txt' | ForEach-Object {
    Get-Content $_ -ErrorAction Continue
}

Dalam contoh ini, Get-Content melaporkan kesalahan yang tidak mengakhiri lalu noSuchFile.txt melanjutkan pemrosesan file3.txt.

Kesalahan yang tidak mengakhiri tidak memicu catch atau trap secara default.

Kesalahan penghentian pernyataan

Kesalahan penghentian pernyataan menghentikan pernyataan saat ini (alur) agar tidak berjalan, tetapi eksekusi berlanjut pada pernyataan berikutnya dalam skrip. Kesalahan penghentian pernyataan dihasilkan oleh:

  • Metode $PSCmdlet.ThrowTerminatingError() dalam fungsi lanjutan dan cmdlet yang dikompilasi
  • Kesalahan mesin seperti CommandNotFoundException (memanggil perintah yang tidak ada) dan ParameterBindingException (argumen parameter tidak valid)
  • Panggilan metode .NET yang melemparkan pengecualian, seperti [int]::Parse('abc')
# Statement-terminating error: Get-Item fails, but the next statement runs
Get-Item -Path 'C:\NoSuchFile.txt'
Write-Output 'This still runs'

Kesalahan penghentian pernyataan dapat ditangkap oleh try/catch dan trap.

Nota

.ThrowTerminatingError() tidak berkonsultasi dengan -ErrorAction parameter (kecuali untuk Break nilai, yang memasuki debugger). Namun, $ErrorActionPreferenceberlaku untuk kesalahan penghentian pernyataan melalui handler tingkat pernyataan mesin. Misalnya, $ErrorActionPreference = 'SilentlyContinue' dapat menekan kesalahan penghentian pernyataan sehingga skrip berlanjut pada pernyataan berikutnya. Parameter -ErrorAction tidak dapat melakukan ini. Untuk detailnya, lihat Asimetri $ErrorActionPreference.

Kesalahan penghentian skrip

Kesalahan penghentian skrip melepas seluruh tumpukan panggilan. Eksekusi berhenti sepenuhnya kecuali kesalahan tertangkap oleh try/catch blok atau trap pernyataan. Kesalahan penghentian skrip dihasilkan oleh:

  • Kata kunci throw
  • Mengurai kesalahan (kesalahan sintaks yang mencegah skrip dikompilasi)
  • Kesalahan yang tidak mengakhiri peningkatan oleh -ErrorAction Stop atau $ErrorActionPreference = 'Stop' dalam konteks non-tingkat lanjut. Untuk informasi selengkapnya, lihat Cara kerja eskalasi.
  • Kegagalan mesin penting tertentu
# Script-terminating error: throw unwinds the call stack
function Test-Throw {
    throw 'Critical failure'
    Write-Output 'This never runs'
}

Test-Throw
Write-Output 'This never runs either (unless caught)'

Kata throw kunci menghasilkan kesalahan penghentian skrip secara default. Namun, $ErrorActionPreferencedapat menekan throw saat diatur ke SilentlyContinue atau Ignore. Saat memanggil fungsi tingkat lanjut dengan -ErrorAction SilentlyContinue, parameter diterjemahkan ke nilai lokal $ErrorActionPreference cakupan, sehingga juga menekan throw di dalam fungsi tersebut.

Nota

Bahkan dengan $ErrorActionPreference = 'Ignore', throw yang ditekan masih mencatat entri di $Error. Nilai Ignore hanya mencegah $Error perekaman untuk kesalahan yang tidak mengakhiri .

Penting

Istilah penghentian pernyataan dan penghentian skrip menjelaskan cakupan dampak, bukan tingkat keparahan kesalahan. Kesalahan penghentian pernyataan menghentikan satu pernyataan. Kesalahan penghentian skrip menghentikan seluruh skrip dan pemanggilnya. Keduanya dapat ditangkap oleh try/catch.

Kesalahan program eksternal

Program eksternal (asli) tidak berpartisipasi dalam sistem kesalahan PowerShell secara langsung. Mereka melaporkan kegagalan melalui kode keluar bukan nol, yang disimpan PowerShell dalam $LASTEXITCODE variabel otomatis.

git clone https://example.com/nonexistent.git 2>$null
if ($LASTEXITCODE -ne 0) {
    Write-Error "git failed with exit code $LASTEXITCODE"
}

Secara default, kode keluar bukan nol dari program asli:

  • Atur $? ke $false
  • Tidak menghasilkan in ErrorRecord$Error
  • Tidak memicu catch atautrap

PowerShell 7.3 menambahkan variabel $PSNativeCommandUseErrorActionPreferencepreferensi eksperimental , yang menjadi fitur stabil di 7.4. Ketika Anda mengatur variabel ini ke $true, itu menyebabkan kode keluar bukan nol memancarkan kesalahan non-mengakhiri yang pesannya menyatakan kode keluar tertentu (a NativeCommandExitException). Kesalahan ini menghormati $ErrorActionPreference, jadi mengaturnya untuk Stop mempromosikan kesalahan ke kesalahan penghentian skrip yang dapat ditangkap dengantry/catch .

Variabel status kesalahan

PowerShell mempertahankan beberapa variabel otomatis yang mencerminkan status kesalahan saat ini.

$?

Berisi $true jika operasi terakhir berhasil dan $false jika menghasilkan kesalahan (tidak mengakhiri atau mengakhiri). Untuk perintah asli, $? diatur berdasarkan kode keluar: $true untuk kode 0keluar , $false jika tidak.

Get-Item -Path 'C:\NoSuchFile.txt' 2>$null
$?  # False

$Error

Yang ArrayList menyimpan rekaman kesalahan terbaru, dengan kesalahan terbaru di indeks 0. Daftar menyimpan hingga $MaximumErrorCount entri (default 256).

Semua kesalahan penghentian ditambahkan ke $Error. Untuk mengakhiri kesalahan, Ignore menekan tampilan tetapi masih merekam kesalahan di $Error. Semua non-penghentian ditambahkan ke $Error kecuali -ErrorAction Ignore digunakan pada kesalahan yang tidak mengakhiri, yang mencegah tampilan dan perekaman.

$LASTEXITCODE

Berisi kode keluar dari program asli terakhir yang berjalan. Nilai 0 konvensional menunjukkan keberhasilan. Nilai bukan nol menunjukkan kegagalan. Variabel ini tidak terpengaruh oleh kesalahan cmdlet PowerShell.

Mengontrol perilaku kesalahan

Parameter -ErrorAction umum

Parameter -ErrorAction umum mengambil $ErrorActionPreference alih untuk satu perintah. Ini mengontrol bagaimana PowerShell merespons kesalahan yang tidak mengakhiri dari perintah tersebut.

Nilai Perilaku
Continue Tampilkan kesalahan dan lanjutkan (default)
SilentlyContinue Sembunyikan tampilan, tambahkan ke $Error, lanjutkan
Ignore Sembunyikan tampilan dan jangan tambahkan ke $Error
Stop Meningkatkan ke kesalahan yang mengakhiri (lihat Cara kerja eskalasi)
Inquire Meminta pengguna untuk membuat keputusan
Break Masukkan debugger

-ErrorAction tidak mengubah perilaku kesalahan yang dihasilkan oleh $PSCmdlet.ThrowTerminatingError(). Kesalahan tersebut selalu mengakhiri pernyataan terlepas dari preferensi pemanggil.

Variabel $ErrorActionPreference

Variabel $ErrorActionPreference preferensi berlaku untuk semua perintah dalam cakupan saat ini dan cakupan anak. Ini menerima nilai yang sama dengan -ErrorAction.

$ErrorActionPreference = 'Stop'
# All non-terminating errors in this scope now become terminating
Write-Error 'This now throws'   # Generates ActionPreferenceStopException

Ketika -ErrorAction ditentukan pada perintah, itu lebih diutamakan untuk $ErrorActionPreference perintah tersebut.

Cara kerja eskalasi

Saat -ErrorAction Stop atau $ErrorActionPreference = 'Stop' berlaku, PowerShell mengonversi kesalahan yang tidak mengakhiri kesalahan menjadi mengakhiri kesalahan menggunakan mekanisme berikut:

  1. Cmdlet memanggil WriteError() secara internal untuk memancarkan kesalahan yang tidak mengakhiri.
  2. Mesin memeriksa preferensi efektif ErrorAction untuk perintah.
  3. Karena preferensinya adalah Stop, mesin membuat yang ActionPreferenceStopException membungkus rekaman kesalahan asli.
  4. Jika tertangkap oleh catch, informasi kesalahan asli dapat diakses melalui $_.Exception.ErrorRecord.

Cakupan kesalahan yang diluaskan tergantung pada konteks:

  • Dalam skrip, fungsi, atau blok skrip non-tingkat lanjut , pengaturan $ErrorActionPreference = 'Stop' meningkat menjadi kesalahan penghentian skrip . Kesalahan menyebarkan tumpukan panggilan.
  • Dalam fungsi lanjutan dan blok skrip (dengan [CmdletBinding()]), kesalahan tetap mengakhiri pernyataan. Eksekusi berlanjut pada pernyataan berikutnya setelah panggilan.
  • Meneruskan -ErrorAction Stop ke fungsi tingkat lanjut memiliki efek yang sama dengan pengaturan $ErrorActionPreference = 'Stop' di dalamnya, karena -ErrorAction diterjemahkan ke nilai lingkup lokal $ErrorActionPreference .

Contoh eskalasi

  • NON-tingkat lanjut: penghentian skrip ('setelah' TIDAK mencetak)

    & {
        param()
        $ErrorActionPreference = 'Stop'
        1/0  # Divide by zero error
    } 2>$null
    'after'
    
  • ADVANCED: statement-terminating ('after' DOES print)

    & {
        [CmdletBinding()]
        param()
        $ErrorActionPreference = 'Stop'
        1/0  # Divide by zero error
    } 2>$null
    'after'
    
  • Tanpa -ErrorAction Stop: tidak mengakhiri, tangkapan tidak berjalan

    try {
        Write-Error 'This is non-terminating'
        Write-Output 'Execution continues'
    } catch {
        Write-Output "Caught: $_"   # Not reached
    }
    
  • Dengan -ErrorAction Stop: meningkat ke penghentian

    try {
        Write-Error 'This becomes terminating' -ErrorAction Stop
    } catch {
        Write-Output "Caught: $_"   # Reached
    }
    

Kesalahan yang diluaskan dapat ditangkap oleh jenis pengecualian aslinya. Mesin membuka bungkus untuk menemukan pengecualian yang mendasar ActionPreferenceStopException :

try {
    Get-Item -Path 'C:\NoSuchFile.txt' -ErrorAction Stop
} catch [System.Management.Automation.ItemNotFoundException] {
    Write-Output "File not found: $($_.Exception.Message)"
}

$ErrorActionPreference Asimetri

Parameter -ErrorAction dan $ErrorActionPreference variabel berulah secara berbeda dengan mengakhiri kesalahan. Penting untuk memahami asimetri ini:

  • -ErrorAction hanya memengaruhi kesalahan yang tidak mengakhiri . Ketika cmdlet memanggil $PSCmdlet.ThrowTerminatingError(), -ErrorAction parameter diabaikan (kecuali untuk Break, yang memasuki debugger). Kesalahan selalu dilemparkan.

  • $ErrorActionPreference memengaruhi kesalahan yang tidak mengakhiri dan mengakhiri pernyataan. Handler kesalahan tingkat pernyataan mesin membaca $ErrorActionPreference (bukan -ErrorAction parameter) dan dapat menekan kesalahan yang mengakhiri pernyataan saat nilainya adalah SilentlyContinue atau Ignore.

function Test-Asymmetry {
    [CmdletBinding()]
    param()
    $er = [System.Management.Automation.ErrorRecord]::new(
        [System.InvalidOperationException]::new('test error'),
        'TestError',
        [System.Management.Automation.ErrorCategory]::InvalidOperation,
        $null
    )
    $PSCmdlet.ThrowTerminatingError($er)
}

# -ErrorAction SilentlyContinue does NOT suppress the error:
Test-Asymmetry -ErrorAction SilentlyContinue   # Error is still thrown

# $ErrorActionPreference DOES suppress the error:
$ErrorActionPreference = 'SilentlyContinue'
Test-Asymmetry   # Error is silently suppressed, script continues
$ErrorActionPreference = 'Continue'

Penting

$ErrorActionPreference tidak dapat menyembunyikan kesalahan yang telah SuppressPromptInInterpreter diatur ke true. Ini selalu menyebar terlepas dari variabel preferensi. Contoh jenis kesalahan ini meliputi:

  • ActionPreferenceStopException dari -ErrorAction Stop eskalasi
  • Kesalahan di dalam metode kelas PowerShell
  • PipelineStoppedException

Menangani kesalahan

try/catch/finally

Gunakan try/catch/finally untuk menangani kesalahan penghentian pernyataan dan penghentian skrip. Ketika kesalahan terjadi di dalam try blok, PowerShell mencari blok yang cocok catch . Blok finally selalu berjalan, apakah terjadi kesalahan atau tidak.

try {
    $result = Get-Content -Path 'data.txt' -ErrorAction Stop
}
catch [System.Management.Automation.ItemNotFoundException] {
    Write-Warning 'Data file not found, using defaults.'
    $result = 'default'
}
catch {
    Write-Warning "Unexpected error: $_"
}
finally {
    Write-Verbose 'Cleanup complete.' -Verbose
}

try Di dalam blok, mesin menetapkan bendera internal yang menyebabkan kesalahan non-penghentian yang ditingkatkan oleh -ErrorAction Stop atau $ErrorActionPreference = 'Stop' menyebar ke catch blok. Ini dirancang perilaku, bukan kasus khusus.

Untuk detail sintaks lengkap, lihat about_Try_Catch_Finally.

trap

Pernyataan ini trap menangani penghentian kesalahan pada tingkat cakupan. Ketika kesalahan terjadi di mana saja dalam cakupan penutup, trap blok berjalan.

  • Default (tidak break atau continue): Kesalahan ditampilkan dan eksekusi berlanjut pada pernyataan berikutnya setelah yang menyebabkan kesalahan.
  • continue dalam perangkap: Menekan pesan kesalahan dan melanjutkan pada pernyataan berikutnya.
  • break dalam perangkap: Kesalahan menyebar ke cakupan induk.
trap [System.Management.Automation.CommandNotFoundException] {
    Write-Warning "Command not found: $($_.TargetObject)"
    continue
}

NonsenseCommand   # Trap fires, execution continues
Write-Output 'This runs because the trap used continue'

Untuk detail sintaks lengkap, lihat about_Trap.

Melaporkan kesalahan dalam fungsi dan skrip

Saat menulis fungsi dan skrip, pilih mekanisme pelaporan kesalahan yang cocok dengan tingkat keparahan kegagalan.

Tidak mengakhiri - gunakan Write-Error

Gunakan Write-Error ketika fungsi dapat terus memproses input lain. Ini sesuai untuk fungsi alur yang memproses beberapa objek dan mengalami kegagalan pada item individual.

function Test-Path-Safe {
    [CmdletBinding()]
    param([Parameter(ValueFromPipeline)][string]$Path)
    process {
        if (-not (Test-Path $Path)) {
            Write-Error "Path not found: $Path"
            return
        }
        $Path
    }
}

Nota

Dalam fungsi lanjutan (dengan [CmdletBinding()]), gunakan $PSCmdlet.WriteError() alih-alih Write-Error untuk memastikan bahwa diatur $? dengan benar ke $false dalam cakupan pemanggil. Write-Error Cmdlet tidak selalu diatur $? dengan benar.

Penghentian pernyataan - gunakan $PSCmdlet.ThrowTerminatingError()

Gunakan $PSCmdlet.ThrowTerminatingError() ketika fungsi tidak dapat dilanjutkan sama sekali tetapi pemanggil harus memutuskan cara menangani kegagalan. Ini adalah pendekatan yang direkomendasikan dalam fungsi lanjutan.

function Get-Config {
  [CmdletBinding()]
  param([string]$Path)

  if (-not (Test-Path $Path)) {
    $er = [System.Management.Automation.ErrorRecord]::new(
      [System.IO.FileNotFoundException]::new("Config file not found: $Path"),
      'ConfigNotFound',
      [System.Management.Automation.ErrorCategory]::ObjectNotFound,
      $Path
    )
    $PSCmdlet.ThrowTerminatingError($er)
  }

  Get-Content $Path | ConvertFrom-Json
}

Setelah kesalahan meninggalkan fungsi, pemanggil memperlakukannya sebagai kesalahan yang tidak mengakhiri secara default. Pemanggil dapat meningkatkannya dengan -ErrorAction Stop.

Penghentian skrip - gunakan throw

Gunakan throw saat pemulihan tidak dimungkinkan dan seluruh skrip harus berhenti.

$config = Get-Content 'config.json' -ErrorAction SilentlyContinue |
    ConvertFrom-Json

if (-not $config) {
    throw 'Cannot proceed without a valid configuration file.'
}

Mekanisme mana yang akan digunakan

  • Saat memproses beberapa input di mana beberapa mungkin gagal, gunakan Write-Error atau $PSCmdlet.WriteError().
  • Jika fungsi tidak dapat dilanjutkan, gunakan $PSCmdlet.ThrowTerminatingError() dan biarkan pemanggil memutuskan cara menanganinya.
  • Jika seluruh skrip harus segera berhenti, gunakan throw.

Ringkasan jenis kesalahan

Tabel berikut ini meringkas properti dan perilaku dari berbagai jenis kesalahan di PowerShell.

Kesalahan non-penghentian

Kesalahan yang tidak mengakhiri dapat dihasilkan oleh Write-Error atau $PSCmdlet.WriteError().

Attribute Deskripsi
Cakupan dampak Alur berlanjut
Tertangkap oleh catch Tidak (kecuali dinaikkan)
Tertangkap oleh trap Tidak (kecuali dinaikkan)
Ditambahkan ke $Error Ya (kecuali Ignore)
Atur $? ke $false Yes
Dipengaruhi oleh -ErrorAction Yes
Dipengaruhi oleh $ErrorActionPreference Yes

Kesalahan penghentian pernyataan

Kesalahan penghentian pernyataan dapat dihasilkan oleh ThrowTerminatingError(), kesalahan mesin, pengecualian metode .NET, atau -ErrorAction Stop dalam konteks lanjutan.

Attribute Deskripsi
Cakupan dampak Pernyataan saat ini berhenti; skrip berlanjut
Tertangkap oleh catch Yes
Tertangkap oleh trap Yes
Ditambahkan ke $Error Yes
Atur $? ke $false Yes
Dipengaruhi oleh -ErrorAction Tidak (Break hanya)
Dipengaruhi oleh $ErrorActionPreference Ya (dapat menekan)

Kesalahan penghentian skrip

Kesalahan penghentian skrip dapat dihasilkan oleh throw, mengurai kesalahan, atau -ErrorAction Stop dalam konteks non-tingkat lanjut.

Attribute Deskripsi
Cakupan dampak Memanggil stack unwinds
Tertangkap oleh catch Yes
Tertangkap oleh trap Yes
Ditambahkan ke $Error Yes
Atur $? ke $false Yes
Dipengaruhi oleh -ErrorAction No
Dipengaruhi oleh $ErrorActionPreference throw: Ya (dapat menekan)
Dipengaruhi oleh $ErrorActionPreference Diluaskan: tergantung pada konteks

Baca juga