2012-01-05 35 views
16

Tôi có kịch bản sau đây,Làm thế nào để nắm bắt ngoại lệ được nêu trong scriptblock của công việc bắt đầu?

$createZip = { 
    Param ([String]$source, [String]$zipfile) 
    Process { 
     echo "zip: $source`n  --> $zipfile" 
     throw "test" 
    } 
} 

try { 
    Start-Job -ScriptBlock $createZip -ArgumentList "abd", "acd" 
    echo "**Don't reach here if error**" 
    LogThezippedFile 
} 
catch { 
    echo "Captured: " 
    $_ | fl * -force 
} 
Get-Job | Wait-Job 
Get-Job | receive-job 
Get-Job | Remove-Job 

Tuy nhiên, ngoại trừ lớn lên ở một ví dụ PowerShell không thể bị bắt. Cách tốt nhất để nắm bắt ngoại lệ là gì?

Id    Name   State  HasMoreData  Location    Command     
--    ----   -----  -----------  --------    -------     
343    Job343   Running True   localhost   ...      
**Don't reach here if error** 
343    Job343   Failed  True   localhost   ...      
zip: abd 
    --> acd 
Receive-Job : test 
At line:18 char:22 
+ Get-Job | receive-job <<<< 
    + CategoryInfo   : OperationStopped: (test:String) [Receive-Job], RuntimeException 
    + FullyQualifiedErrorId : test 
+0

tôi đã cập nhật câu trả lời của tôi để cho bạn biết câu hỏi trước đó của bạn như thế nào. –

+0

Nó không rõ ràng những gì bạn đang cố gắng để thực hiện với công việc. Có vẻ như bạn muốn cả hành vi không đồng bộ và đồng bộ cùng một lúc, điều đó là không thể. Khi nào bạn muốn thực thi dòng tiếp theo trong tập lệnh của mình? – zdan

Trả lời

19

Sử dụng throw sẽ thay đổi thuộc tính State đối tượng công việc để "Không". Điều quan trọng là sử dụng đối tượng công việc được trả lại từ Start-Job hoặc Get-Job và kiểm tra thuộc tính State. Sau đó, bạn có thể truy cập thông điệp ngoại lệ từ chính đối tượng công việc đó.

Theo yêu cầu của bạn, tôi đã cập nhật ví dụ để bao gồm cả đồng thời.

$createZip = { 
    Param ([String] $source, [String] $zipfile) 

    if ($source -eq "b") { 
     throw "Failed to create $zipfile" 
    } else { 
     return "Successfully created $zipfile" 
    } 
} 

$jobs = @() 
$sources = "a", "b", "c" 

foreach ($source in $sources) { 
    $jobs += Start-Job -ScriptBlock $createZip -ArgumentList $source, "${source}.zip" 
} 

Wait-Job -Job $jobs | Out-Null 

foreach ($job in $jobs) { 
    if ($job.State -eq 'Failed') { 
     Write-Host ($job.ChildJobs[0].JobStateInfo.Reason.Message) -ForegroundColor Red 
    } else { 
     Write-Host (Receive-Job $job) -ForegroundColor Green 
    } 
} 
+0

Cảm ơn, tôi đã cập nhật câu hỏi - Tôi không muốn ghi nhật ký sau khi quá trình nén được thực hiện nếu xảy ra lỗi. Có thể không? – ca9163d9

+0

@NickW Sure is. Xem câu trả lời cập nhật của tôi. –

+0

Cảm ơn. Tuy nhiên, 'Wait-Job' sẽ chặn việc thực hiện các câu lệnh trong khối try, nó sẽ được chạy trong một vòng lặp lớn. Mục đích của tôi sử dụng công việc bắt đầu là để song song nhiệm vụ trong vòng lặp chính và nén ... Có vẻ như tôi đang tìm kiếm một số thực thi không đồng bộ ... – ca9163d9

5

Đây phải là nhận xét thực sự, nhưng tôi không có tiếng để lại nhận xét.

câu trả lời của tôi là bạn nên sử dụng câu trả lời Andy Arismendi, nhưng cũng ra $job.ChildJobs[0].Error

Như $job.ChildJobs[0].JobStateInfo.Reason.Message không phải lúc nào cũng hữu ích.

+0

Đối với tôi, quyền truy cập vào đối tượng ngoại lệ là '$ job.ChildJobs [0] .JobStateInfo.Reason'. Tôi cũng có thể 'làm lại' lỗi. ChicldJobs [0] .Lỗi trống. – Patrick

2

tôi đã có thể "rethrow" ngoại trừ trong các chủ đề chính bằng cách sử dụng:

Receive-Job $job -ErrorAction Stop 

tôi sẽ trường hợp sử dụng của tôi như là một ví dụ. Nó có thể dễ dàng được áp dụng cho OP.

$code = { 
    $Searcher = New-Object -ComObject Microsoft.Update.Searcher 
    #Errors from Search are not terminating, but will be present in the output none the less. 
    $Results = $Searcher.Search('IsInstalled=0 and IsHidden=0') 
    $Results.Updates 
}; 
$job = Start-Job -ScriptBlock $code; 
$consume = Wait-Job $job -Timeout 600; 

if ($job.state -eq 'Running') { 
    Stop-Job $job 
    throw 'Windows update searcher took more than 10 minutes. Aborting' 
}; 

#Captures and throws any exception in the job output 
Receive-Job $job -ErrorAction Stop; 
Write-Host "Finished with no errors"; #this will not print if there was an error 

Làm việc trong v2.0.

Lưu ý rằng nếu lỗi trong công việc không kết thúc, các dòng tiếp theo sẽ tiếp tục thực thi. Nhưng, điều này sẽ không rõ ràng trong đầu ra được trả về từ Receive-Job, như Receive-Job "chấm dứt nửa chiều thorugh" - nó ném ra khỏi chính nó khi đối tượng lỗi gặp phải.

Một cách để tránh điều đó là để bọc toàn bộ khối trong một catch {} {throw;}

Ngoài ra, tình trạng công việc sẽ không được 'Không' nếu ngoại lệ là không chấm dứt

Các vấn đề liên quan