2013-07-04 13 views
7

đoạn của tôi là một cái gì đó như thế này:Cách lấy mã lỗi khi có lỗi trong PowerShell?

$msg=Remove-Item -Recurse -Force C:\users\bkp 2>&1 
if ($LASTEXITCODE -eq 1) 
{ 
    "Encountered error during Deleting the Folder. Error Message is $msg. Please check." >> $LogFile 
    exit 
} 

Các thư mục C: \ Users \ BKP không tồn tại. Mặc dù $ msg cung cấp cho tôi thông báo lỗi $ LASTEXITCODE vẫn là 0. Làm cách nào để chụp dưới dạng cờ?

+0

Bạn chỉ có thể kiểm tra biến lỗi $. Điều này có chứa tất cả các lỗi gặp phải trong phiên của bạn, cũng lên đến một điểm vì nó có một giới hạn về cấp phát bộ nhớ tôi tin. –

Trả lời

9

$ LASTEXITCODE hoàn toàn dành cho các chương trình dòng lệnh để trả lại trạng thái của chúng. Cmdlets được tích hợp vào PS, chẳng hạn như Remove-item trả về lỗi của chúng theo 3 cách. Đối với cảnh báo, họ viết thư (hoặc các đối tượng .NET khác) vào "dòng cảnh báo". Trong PSv3 có một cách đơn giản để chuyển hướng luồng đó tới một tệp: cmdlet blah blah blah 3>warning.out. Thứ hai là thông qua luồng lỗi. Luồng đó có thể được chuyển hướng cũng như ... 2>error.out hoặc các lỗi thông thường hơn bị bắt với try/catch hoặc trap hoặc được ghi vào một biến với tham số -ErrorVariable (xem help about_commonparameters). Cách thứ ba là các lỗi được "ném". Trừ khi bị bắt (try/catch hoặc trap), một lỗi được ném sẽ khiến kịch bản chấm dứt. Lỗi phổ biến thường là các lớp con của lớp .NET system.Management.Automation.ErrorRecord. ErrorRecord cung cấp nhiều thông tin hơn về lỗi hơn mã trả về.

Nếu xóa mục không thành công do lỗi không tìm thấy tệp, nó ghi System.Management.Automation.ItemNotFoundException vào luồng lỗi. Sử dụng try/catch, bạn có thể lọc lỗi cụ thể hoặc các lỗi cụ thể khác từ mục xóa. Nếu bạn chỉ cần gõ lệnh PS từ dòng lệnh, bạn có thể nhập $error[0]|select-object * để nhận được nhiều thông tin về lỗi cuối cùng.


Bạn có thể làm điều này:

try { 
    Remove-Item -Recurse -Force C:\users\bkp 2>&1 
} catch { 
    # oops remove-item failed. Write warning then quit 
    # replace the following with what you want to do 
    write-warning "Remove-item encounter error: $_" 
    return # script failed 
} 
+0

có không đặt cờ báo lỗi không? –

+0

Âm thanh như bạn chỉ muốn biết liệu lệnh có hoạt động hay không? Tuy nhiên nó không phải lúc nào cũng chỉ là một quyết định có/không. Ví dụ: bạn có thể yêu cầu xóa mục để xóa 10 tệp nhưng kết quả là xóa 8 tệp vì hai tệp khác đang được các chương trình khác sử dụng. Bạn có xem xét thành công hay thất bại không? Tôi nghĩ rằng bạn có thể muốn sử dụng try/catch (xem help about_try) và nếu có lỗi xảy ra thì bạn muốn bắt lỗi và đi từ đó. Tôi sẽ chỉnh sửa câu trả lời để đưa ra một số mã mẫu –

+2

'try..catch' không hoạt động, bởi vì lỗi không kết thúc. Bạn phải thêm '-ErrorAction Stop' vào' Remove-Item' để làm cho lỗi có thể bắt được. –

12

Bạn có thể sử dụng $?automatic variable để xác định kết quả của lệnh cuối cùng. Nếu bạn cần truy cập vào lỗi thực tế, bạn có thể sử dụng biến số tự động $Error. Mục đầu tiên trong mảng là lỗi cuối cùng được ném:

Remove-Item -Recurse -Force C:\users\bkp 2>&1 
if(-not $?) 
{ 
    $msg = $Error[0].Exception.Message 
    "Encountered error during Deleting the Folder. Error Message is $msg. Please check." >> $LogFile 
    exit 
} 
+0

Tuyệt vời .. Hãy để tôi thử và lấy lại .. –

+1

Tôi nghĩ rằng nó sẽ là tốt hơn để thêm '-ErrorAction SilentlyContinue', do đó nếu lệnh ghép ngắn thất bại do nó sẽ không chấm dứt và bỏ qua nếu tuyên bố. và thông báo lỗi sẽ không được in tới bàn điều khiển hai lần. – Jackie

+0

@Jackie Có, nếu OP muốn tự xử lý tất cả các lỗi. Tuy nhiên, từ câu hỏi ban đầu của mình, anh ta đang chuyển hướng lỗi tới luồng đầu ra tiêu chuẩn, vì vậy tôi nghĩ anh ấy vẫn muốn xem chúng. –