시작 작업의 스크립트 블록에 제기된 예외를 캡처하는 방법은?
나는 다음과 같은 대본을 가지고 있습니다.
$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
그러나 다른 파워셸 인스턴스에서 제기된 예외는 캡처할 수 없습니다.예외를 포착하는 가장 좋은 방법은 무엇입니까?
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
사용.throw작업 개체를 변경합니다.State"Failed"에 속성을 지정합니다.핵심은 반환되는 작업 개체를 사용하는 것입니다.Start-Job아니면Get-Job확인해보세요.State소유물.그런 다음 작업 개체 자체에서 예외 메시지에 액세스할 수 있습니다.
당신의 요청에 따라 나는 동시성도 포함하도록 예제를 업데이트 했습니다.
$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
}
}
이건 정말 댓글이어야 하는데, 저는 댓글을 달 수 있는 평판이 없습니다.
내 대답은 Andy Arismendi의 답변을 사용하되 출력도 사용해야 한다는 것입니다.$job.ChildJobs[0].Error
~하듯이$job.ChildJobs[0].JobStateInfo.Reason.Message항상 유용한 것은 아닙니다.
다음을 사용하여 메인 스레드에서 예외를 "되돌릴" 수 있었습니다.
Receive-Job $job -ErrorAction Stop
저의 용례를 예로 들겠습니다.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
v2.0에서 작동합니다.
작업 내의 오류가 종료되지 않은 경우 다음 행이 계속 실행됩니다.그러나 수신 작업에서 반환되는 출력에서는 명확하지 않습니다. 수신 작업은 오류 개체가 발생하면 자체적으로 폐기되기 때문입니다.
이를 방지하는 한 가지 방법은 전체 블록을 시도 {}개의 캐치{throw;}에 래핑하는 것입니다.
또한 예외가 종료되지 않는 경우 작업 상태가 '실패' 상태가 되지 않습니다.
TLDR:
# Works with both terminating and non terminating errors
$j = start-job {1/0} | wait-job; try { receive-job $j -ErrorAction Stop } catch { "err $_" }
언급URL : https://stackoverflow.com/questions/8751187/how-to-capture-the-exception-raised-in-the-scriptblock-of-start-job
'programing' 카테고리의 다른 글
| 쓰기가 버퍼에 지속적으로 4K 바이트를 남기는 이유는 무엇입니까? (0) | 2023.10.27 |
|---|---|
| RxJS - 오류가 발생하면 관측 가능이 완료되지 않습니다. (0) | 2023.10.27 |
| Python의 추상 속성 (0) | 2023.10.27 |
| PHP 준비문 SQL with where 값 (0) | 2023.10.27 |
| MySQL에서 grave accent(일명 백틱) 인용 문자의 의미는 무엇입니까? (0) | 2023.10.27 |