RPC_E_SERVERCALL_RETRYLATER خلال أتمتة بوويرشيل
-
05-07-2019 - |
سؤال
وأنا باستخدام PowerShell لأتمتة اي تيونز لكن العثور على معالجة الأخطاء / انتظار للكائنات كوم التعامل مع لتكون أقل من المستوى الأمثل.
وكود مثال
#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
والذهاب الى اي تيونز والقيام بشيء ما يجعله يطفو على الرسالة - في حالتي أنا الخوض في المراوغة الحزب وأحصل على لافتة "حزب خلط تلقائيا بلاه بلاه ...." مع رسالة "عدم عرض" .
وعند هذه النقطة إذا تشغيل البرنامج النصي سوف نفعل ذلك مرارا وتكرارا:
+ 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)) {
وهذا سوف يكون ذلك بسبب التعامل مع المكتبة $ غير صالح.
إذا بلدي على سبيل المثال كان يفعل شيء مهم - مثل تحويل المسارات وثم حذف القديمة، وليس التعامل مع الخطأ بشكل صحيح يمكن أن تكون قاتلة لمسارات في اي تيونز. أريد أن تتصلب عن رمز بحيث يتعامل مع اي تيونز كونه مشغول وسوف إعادة المحاولة بصمت حتى انها النجاح. أي اقتراحات؟
المحلول
إليك وظيفة لإعادة المحاولة العمليات، والتوقف بين الفشل:
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
لمنع البرنامج النصي من تنفيذ أي بيانات أخرى.
نصائح أخرى
والدعم COM في PowerShell غير قابلة موثوقة 100٪. ولكن أعتقد أن القضية الحقيقية هي اي تيونز نفسها. لم يتم تصميم التطبيق وCOM نموذج، IMO، لهذا النوع من الإدارة. قال ذلك، هل يمكن تنفيذ فخ في السيناريو الخاص بك. إذا تم رفع استثناء، هل يمكن أن يكون النوم النصي لبضع ثوان.
وجزء من المشكلة قد تكون في الكيفية التي يتم بها تقييم $ Track.name. قد تتمكن من محاولة إجبارها على إجراء تقييم كامل الاسم باستخدام $ ($ Track.name).
واحد الشيء الآخر الذي قد تحاول يستخدم المعلمة -strict مع قيادة وجوه الجديد /