Windows Server 2025 / Menangani kesalahan PowerShell dan mencatat log eksekusi

Gunakan try, catch, dan finally bersama penanganan kesalahan yang eksplisit serta log terpisah untuk setiap eksekusi PowerShell. Dengan begitu, kegagalan dan hasil parsial dapat ditelusuri; selesainya sebuah perintah belum membuktikan bahwa seluruh tugas administrasi berhasil.

Buat kegagalan terlihat

Latihan ini membaca file dan menulis log tanpa mengubah peran, layanan, atau jaringan server. Skrip instalasi atau pengelolaan akun yang sebenarnya juga harus mencatat perubahan yang sudah terjadi sebelum suatu langkah gagal. Masuk ke catch tidak otomatis membatalkan tindakan sebelumnya.

Sebagian kesalahan membiarkan PowerShell melanjutkan eksekusi dan secara bawaan tidak memicu catch. Menaruh perintah di dalam try saja tidak cukup: -ErrorAction Stop mengubah kesalahan nonterminasi yang didukung menjadi kesalahan terminasi yang dapat ditangkap. Dokumentasi penanganan kesalahan PowerShell menjelaskan perbedaannya.

Siapkan file input dan skrip lengkap

Buat C:\LabScripts terlebih dahulu, lalu simpan C:\LabScripts\input.txt dengan tepat satu baris teks literal lab ready. Simpan seluruh kode berikut sebagai C:\LabScripts\Read-LabFile.ps1 dan periksa ekstensi .txt serta .ps1. Gunakan UTF-8; jika menambahkan karakter non-ASCII pada skrip, pilih UTF-8 dengan penanda urutan byte (BOM, byte order mark), sesuai panduan pengodean karakter. Jalankan dengan Windows PowerShell 5.1 dan izin untuk membaca input serta membuat atau menulis C:\LabLogs. Skrip menyimpan data terstruktur dalam format JSON (JavaScript Object Notation), dengan nama file yang memuat stempel waktu dan pengenal singkat.

param(
    [Parameter(Mandatory=$true)]
    [string]$InputPath
)
$logDirectory = 'C:\LabLogs'
New-Item -ItemType Directory -Path $logDirectory -Force -ErrorAction Stop | Out-Null
$runLabel = (Get-Date -Format 'yyyyMMdd-HHmmss') + '-' + ([guid]::NewGuid().ToString('N').Substring(0,6))
$logPath = Join-Path $logDirectory ($runLabel + '.json')
$result = [ordered]@{
    StartedAt = (Get-Date).ToString('o')
    ComputerName = $env:COMPUTERNAME
    InputPath = $InputPath
    Success = $false
    LineCount = $null
    ErrorId = $null
    ErrorMessage = $null
}
$exitStatus = 0
try {
    $lines = @(Get-Content -LiteralPath $InputPath -ErrorAction Stop)
    $result.LineCount = $lines.Count
    $result.Success = $true
}
catch {
    $result.ErrorId = $_.FullyQualifiedErrorId
    $result.ErrorMessage = $_.Exception.Message
    $exitStatus = 1
    Write-Warning $result.ErrorMessage
}
finally {
    $result.FinishedAt = (Get-Date).ToString('o')
    $result | ConvertTo-Json | Set-Content -LiteralPath $logPath -Encoding UTF8 -ErrorAction Stop
}
Write-Output $logPath
exit $exitStatus

Bandingkan keberhasilan dan kegagalan dalam kondisi yang sama

Jalankan baris perintah dari konsol PowerShell. Setiap powershell.exe memulai proses anak, sehingga exit mengakhiri proses tersebut dan konsol asal tetap tersedia. Jalankan dahulu perintah untuk file yang ada, lalu segera baca $LASTEXITCODE. Setelah itu, ulangi pasangan perintah dengan missing-input.txt, yang harus benar-benar tidak ada. Jangan menghapus input yang valid atau mengubah file sistem untuk memicu kegagalan:

powershell.exe -NoProfile -File 'C:\LabScripts\Read-LabFile.ps1' -InputPath 'C:\LabScripts\input.txt'
$LASTEXITCODE
powershell.exe -NoProfile -File 'C:\LabScripts\Read-LabFile.ps1' -InputPath 'C:\LabScripts\missing-input.txt'
$LASTEXITCODE

Untuk input satu baris, pemanggilan pertama harus menghasilkan kode keluar 0 dan JSON dengan Success=true serta LineCount=1, tanpa detail kesalahan. Input yang tidak ada harus menghasilkan 1, Success=false, dan LineCount=null, dengan ErrorId serta ErrorMessage terisi. Isi pesan dapat berbeda sesuai bahasa sistem. Buka file JSON pada jalur yang dicetak setiap eksekusi menggunakan editor teks, lalu periksa InputPath, ComputerName, StartedAt, dan FinishedAt. Bandingkan kedua log baru tersebut, bukan file lama dalam folder.

Jika kebijakan memblokir eksekusi skrip, penuhi persyaratan eksekusi dan tanda tangan organisasi. Jangan melemahkan pengaturan global untuk contoh ini.

Pahami setiap bagian penanganan kesalahan

Bagian Tujuan dalam skrip ini
try Membaca file dan mencatat jumlah barisnya
catch Mencatat pengenal serta pesan kesalahan yang ditangkap dan menentukan kode keluar kegagalan
finally Mencoba menyimpan hasil, baik pembacaan berhasil maupun gagal

Referensi try, catch, dan finally dari Microsoft menjelaskan penanganan kesalahan terminasi. Pembuatan C:\LabLogs dalam skrip ini berada sebelum try; jika persiapan itu gagal, catch setelahnya tidak menangkap kegagalan tersebut. finally mencoba menyimpan hasil, tetapi tidak menjamin ruang kosong atau izin tulis. Success mencerminkan pembacaan file, jadi pastikan pula ada JSON baru yang valid. Penulisan log juga menggunakan -ErrorAction Stop. Tidak adanya log bukan bukti bahwa tugas selesai tanpa kesalahan.

Program eksternal mengembalikan kode keluar sendiri. Di Windows PowerShell 5.1, kode selain nol tidak otomatis memicu catch. Periksa $LASTEXITCODE segera setelah program selesai dan gunakan throw untuk menghasilkan kesalahan terminasi bila diperlukan. Program eksternal berikutnya dapat mengganti nilai tersebut; -ErrorAction Stop saja tidak mengubah kode keluar eksternal menjadi pengecualian.

Tentukan kriteria untuk mengulang tugas dengan aman

  • Catat server, target, serta waktu mulai dan selesai.
  • Periksa keadaan yang sudah ada untuk menghindari pembuatan duplikat atau penimpaan yang tidak disengaja.
  • Catat langkah yang berhasil dan gagal secara terpisah.
  • Jangan masukkan kata sandi, token, atau isi file pengguna yang tidak diperlukan ke dalam log.
  • Jika menerapkan rollback untuk membatalkan perubahan, dokumentasikan cakupannya dan setiap kegagalan pemulihan.

Gunakan kembali jalur input.txt dan jalankan ulang untuk memeriksa kode keluar baru 0 serta JSON baru dengan Success=true dan LineCount=1. Simpan bukti yang diperlukan sebelum menghapus hanya file sementara latihan yang sudah diidentifikasi. Menambahkan SilentlyContinue ke semua perintah menyembunyikan kesalahan dan tidak menggantikan penanganannya.