PowerShell 자동화 중 rpc_e_servercall_retrylater
-
05-07-2019 - |
문제
PowerShell을 사용하여 iTunes를 자동화하지만 COM 객체 처리가 최적이 아닌 오류 처리 / 대기를 찾습니다.
예제 코드
#Cause an RPC error
$iTunes = New-Object -ComObject iTunes.Application
$LibrarySource = $iTunes.LibrarySource
# Get "playlist" objects for main sections
foreach ($PList in $LibrarySource.Playlists)
{
if($Plist.name -eq "Library") {
$Library = $Plist
}
}
do {
write-host -ForegroundColor Green "Running a loop"
foreach ($Track in $Library.Tracks)
{
foreach ($FoundTrack in $Library.search("$Track.name", 5)) {
# do nothing... we don't care...
write-host "." -nonewline
}
}
} while(1)
#END
iTunes로 가서 메시지를 팝업하는 일을하십시오. 제 경우에는 파티 셔플로 들어가서 "파티 셔플을 자동으로 Blah blah ...."메시지를 표시합니다.
이 시점에서 스크립트를 실행하면 반복적으로 다음을 수행합니다.
+ foreach ($FoundTrack in $Library.search( <<<< "$Track.name", 5)) {
Exception calling "Search" with "2" argument(s): "The message filter indicated
that the application is busy. (Exception from HRESULT: 0x8001010A (RPC_E_SERVER
CALL_RETRYLATER))"
At C:\Documents and Settings\Me\My Documents\example.ps1:17 char:45
+ foreach ($FoundTrack in $Library.search( <<<< "$Track.name", 5)) {
Exception calling "Search" with "2" argument(s): "The message filter indicated
that the application is busy. (Exception from HRESULT: 0x8001010A (RPC_E_SERVER
CALL_RETRYLATER))"
At C:\Documents and Settings\Me\My Documents\example.ps1:17 char:45
예제를 실행하기 전에 대화 상자가있을 때까지 기다렸다면 대신 반복적으로 얻을 수 있습니다.
Running a loop
You cannot call a method on a null-valued expression.
At C:\Documents and Settings\Me\example.ps1:17 char:45
+ foreach ($FoundTrack in $Library.search( <<<< "$Track.name", 5)) {
$ 라이브러리 핸들이 유효하지 않기 때문입니다.
내 예제가 트랙을 변환 한 다음 오래된 트랙을 삭제하는 것과 같은 중요한 일을하고 있다면 오류를 올바르게 처리하지 않으면 iTunes의 트랙에 치명적일 수 있습니다. 코드를 강화하여 iTunes가 바쁘게 처리하고 성공할 때까지 조용히 재 시도 할 것입니다. 제안이 있습니까?
해결책
다음은 실패 사이를 일시 중지하는 작업을 재 시도하는 기능입니다.
function retry( [scriptblock]$action, [int]$wait=2, [int]$maxRetries=100 ) {
$results = $null
$currentRetry = 0
$success = $false
while( -not $success ) {
trap {
# Set status variables at function scope.
Set-Variable -scope 1 success $false
Set-Variable -scope 1 currentRetry ($currentRetry + 1)
if( $currentRetry -gt $maxRetries ) { break }
if( $wait ) { Start-Sleep $wait }
continue
}
$success = $true
$results = . $action
}
return $results
}
예제의 첫 번째 오류는 내부를 변경할 수 있습니다. foreach
다음과 같은 루프 :
$FoundTracks = retry { $Library.search( "$Track.name", 5 ) }
foreach ($FoundTrack in $FoundTracks) { ... }
기본값을 사용합니다 $wait
그리고 $maxRetries
, 그래서 그것은 전화를 시도 할 것입니다 $Library.search
100 번, 각 시도마다 2 초를 기다립니다. 모든 재 검색이 실패하면 마지막 오류는 외부 범위로 전파됩니다. 당신은 설정할 수 있습니다 $ErrorActionPreference
에게 Stop
스크립트가 더 이상의 설명을 실행하지 못하게합니다.
다른 팁
PowerShell의 Com 지원은 100% 신뢰할 수 없습니다. 그러나 실제 문제는 iTunes 자체라고 생각합니다. 응용 프로그램 및 COM 모델은 이러한 유형의 관리를 위해 IMO가 설계되지 않았습니다. 즉, 스크립트에 함정을 구현할 수 있습니다. 예외가 제기되면 몇 초 동안 스크립트를 잠들 수 있습니다.
문제의 일부는 $ track.name을 평가하는 방법에있을 수 있습니다. $ ($ track.name)을 사용하여 이름을 완전히 평가하도록 강요 할 수 있습니다.
당신이 시도 할 수있는 또 다른 것은 새로운 객체 명령/와 함께 -strict 매개 변수를 사용하는 것입니다.