PowerShell là công cụ mạnh mẽ cho quản trị hệ thống và tự động hóa tác vụ trên Windows. Tuy nhiên, trong quá trình viết script, lỗi là điều không thể tránh khỏi. Hiểu và áp dụng đúng cách xử lý lỗi trong PowerShell không chỉ giúp script chạy ổn định mà còn tiết kiệm thời gian debug. Bài viết này sẽ giúp bạn làm chủ kỹ thuật bắt lỗi, phân loại lỗi, và tối ưu hóa luồng xử lý để script vận hành trơn tru trong mọi tình huống thực tế.
Bản chất của lỗi trong PowerShell

PowerShell phân chia lỗi thành hai loại chính: lỗi kết thúc (terminating errors) và lỗi không kết thúc (non-terminating errors). Lỗi kết thúc dừng ngay lập tức việc thực thi script, trong khi lỗi không kết thúc chỉ ghi lại thông báo lỗi nhưng script vẫn tiếp tục chạy. Sự khác biệt này ảnh hưởng trực tiếp đến cách bạn triển khai cách xử lý lỗi trong PowerShell.
Khi một lỗi kết thúc xảy ra, PowerShell dừng pipeline và nhảy đến khối catch nếu có. Ngược lại, lỗi không kết thúc thường xuất hiện khi cmdlet gặp sự cố với một phần tử trong pipeline, ví dụ: lệnh Get-ChildItem không tìm thấy file trong thư mục con nào đó. Hiểu rõ bản chất này giúp bạn lựa chọn phương pháp xử lý phù hợp cho từng loại lỗi.
Phân loại lỗi trong PowerShell

| Loại lỗi | Đặc điểm | Ví dụ |
|---|---|---|
| Terminating Error | Dừng script ngay lập tức, có thể bắt bằng try/catch | Lỗi cú pháp, lỗi biến không tồn tại |
| Non-Terminating Error | Ghi lỗi nhưng script vẫn chạy tiếp | Lỗi truy cập file bị từ chối, Get-Service không tìm thấy service |
| Warning/Information | Không phải lỗi thực sự, chỉ thông báo | Write-Warning, Write-Verbose |
Cách xác định loại lỗi khi viết script
Để xác định lỗi thuộc loại nào, và $Error. $? trả về True nếu lệnh cuối cùng thành công, False nếu thất bại. Biến $Error là mảng chứa tất cả lỗi trong phiên làm việc. Trong cách xử lý lỗi trong PowerShell, việc kiểm tra $? sau mỗi lệnh giúp bạn chủ động phản ứng với lỗi không kết thúc.
Các kỹ thuật xử lý lỗi trong PowerShell

1. Sử dụng try/catch/finally
try/catch là phương pháp phổ biến nhất để bắt lỗi kết thúc. Cấu trúc này cho phép bạn định nghĩa hành động cụ thể khi lỗi xảy ra. Khối finally luôn được thực thi, dù có lỗi hay không, thường dùng để dọn dẹp tài nguyên như đóng kết nối hoặc xóa file tạm.
try { Get-Item -Path "C:Nonexistentfile.txt" -ErrorAction Stop
}
catch { Write-Host "Lỗi: $($_.Exception.Message)"
}
finally { Write-Host "Hoàn tất kiểm tra"
}
Tham số -ErrorAction Stop biến lỗi không kết thúc thành lỗi kết thúc để try/catch có thể bắt được. Đây là thủ thuật quan trọng trong cách xử lý lỗi trong PowerShell khi bạn muốn kiểm soát mọi lỗi từ cmdlet.
2. Xử lý lỗi không kết thúc với ErrorAction
PowerShell cung cấp tham số ErrorAction với các giá trị: Continue (mặc định), Stop, SilentlyContinue, Ignore, Inquire. SilentlyContinue ẩn lỗi nhưng vẫn ghi vào $Error. Stop chuyển lỗi thành kết thúc. Ignore hoàn toàn bỏ qua lỗi, không ghi vào $Error. Việc chọn đúng ErrorAction là kỹ năng cốt lõi trong cách xử lý lỗi trong PowerShell.
Get-ChildItem -Path "C:System Volume Information" -ErrorAction SilentlyContinue
Lệnh trên sẽ không hiển thị lỗi truy cập bị từ chối, script vẫn chạy tiếp. Tuy nhiên, cần thận trọng vì SilentlyContinue có thể che giấu vấn đề nghiêm trọng.
3. Kiểm tra biến $Error và $LASTEXITCODE
Biến $Error lưu trữ toàn bộ lỗi trong phiên làm việc dưới dạng mảng. sau vòng lặp.
- Không bắt được lỗi từ remote session: Lỗi từ Invoke-Command cần xử lý riêng với $Error trong session.
- Thứ tự ưu tiên: Trap có thể bị ghi đè bởi try/catch trong cùng scope.
- Bảo mật: Không hiển thị thông tin nhạy cảm trong thông báo lỗi.
Ứng dụng thực tế: Xử lý lỗi khi tự động hóa tác vụ hàng ngày
Ví dụ 1: Kiểm tra kết nối mạng và ghi log
$computers = @("server1", "server2", "server3")
foreach ($computer in $computers) { try { $result = Test-Connection -ComputerName $computer -Count 1 -ErrorAction Stop Write-Host "$computer: OK" } catch { Write-Warning "$computer: Không ping được - $($_.Exception.Message)" Add-Content -Path "C:logsping_failures.txt" -Value "$(Get-Date) - $computer" }
}
Đoạn script trên minh họa cách xử lý lỗi trong PowerShell cho tác vụ quét mạng. Nếu một máy không phản hồi, lỗi được ghi vào file log thay vì dừng toàn bộ quá trình.
Ví dụ 2: Xử lý lỗi khi tạo thư mục trên nhiều máy
$remoteComputers = @("PC01", "PC02", "PC03")
$folderPath = "C:Backup"
foreach ($computer in $remoteComputers) { try { Invoke-Command -ComputerName $computer -ScriptBlock { New-Item -Path $using:folderPath -ItemType Directory -Force -ErrorAction Stop } -ErrorAction Stop Write-Host "$computer: Tạo thư mục thành công" } catch { Write-Error "Lỗi trên $computer: $($_.Exception.Message)" }
}
Ví dụ 3: Xử lý lỗi khi import module không tồn tại
Khi module chưa được cài đặt, lệnh Import-Module sẽ gây lỗi kết thúc. sau các lệnh quan trọng nếu không dùng try/catch.
Câu hỏi thường gặp về cách xử lý lỗi trong PowerShell

Làm thế nào để bắt tất cả lỗi trong PowerShell?
Sử dụng try/catch với [System.Exception] hoặc đặt $ErrorActionPreference = “Stop” ở đầu script. Bạn cũng có thể dùng Trap để bắt lỗi toàn cục nhưng không nên lạm dụng.
Sự khác nhau giữa ErrorAction Stop và SilentlyContinue là gì?
-Stop biến lỗi không kết thúc thành kết thúc, script dừng và ném exception. -SilentlyContinue ẩn thông báo lỗi nhưng script vẫn chạy, lỗi vẫn được ghi vào biến $Error.
Có thể xử lý lỗi trong pipeline không?
Có, bằng cách dùng ForEach-Object kết hợp try/catch hoặc dùng tham số -ErrorAction trên từng cmdlet trong pipeline. Nên dùng khối script block với try/catch trong pipeline.
Tại sao try/catch không bắt được lỗi từ lệnh Get-ChildItem?
Vì Get-ChildItem tạo lỗi không kết thúc. Bạn cần thêm -ErrorAction Stop để chuyển thành lỗi kết thúc.
Làm sao để xử lý lỗi khi gọi chương trình bên ngoài (exe)?
Kiểm tra $LASTEXITCODE sau khi chạy exe. Ví dụ: ping.exe google.com; if ($LASTEXITCODE -ne 0) {… }
Kết luận
Nắm vững cách xử lý lỗi trong PowerShell là kỹ năng không thể thiếu đối với bất kỳ quản trị viên hệ thống hay nhà phát triển nào. Từ try/catch cơ bản đến các thủ thuật với ErrorActionPreference và Trap, mỗi phương pháp đều có ưu nhược điểm riêng. Áp dụng linh hoạt tùy theo tình huống sẽ giúp script của bạn vận hành ổn định, dễ bảo trì và chuyên nghiệp hơn. Hãy luôn kiểm tra kỹ lỗi trong môi trường test trước khi chạy thực tế, và đừng quên ghi log để hỗ trợ debug sau này.







