Pregunta

Estoy usando PowersHell para automatizar iTunes pero encuentro que el manejo de errores / la espera de que el manejo de objetos com sea menos que óptimo.

Código de ejemplo

#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 

Entra en iTunes y haz algo que lo haga aparecer en un mensaje: en mi caso, entro en Party Shuffle y recibo una pancarta "Party shuffle automatic bla bla ..." con un " No mostrar " mensaje.

En este punto, si la ejecución del script lo hará repetidamente:

+      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

Si esperó hasta tener un cuadro de diálogo antes de ejecutar el ejemplo, en su lugar obtendrá esto repetidamente:

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)) {

Eso será porque el identificador de $ Library no es válido.

Si mi ejemplo estaba haciendo algo importante, como convertir pistas y luego eliminar las antiguas, no manejar el error correctamente podría ser fatal para las pistas en iTunes. Quiero reforzar el código para que se ocupe de que iTunes esté ocupado y volveré a intentarlo en silencio hasta que tenga éxito. ¿Alguna sugerencia?

¿Fue útil?

Solución

Aquí hay una función para reintentar las operaciones, haciendo una pausa entre fallas:

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
}

Para el primer error en su ejemplo, podría cambiar el bucle interno foreach de esta manera:

$FoundTracks = retry { $Library.search( "$Track.name", 5 ) }
foreach ($FoundTrack in $FoundTracks) { ... }

Esto usa los valores predeterminados para $ wait y $ maxRetries , por lo que intentará llamar a $ Library.search 100 veces, esperando 2 segundos entre cada intento. Si todos los reintentos fallan, el último error se propagará al ámbito externo. Puede establecer $ ErrorActionPreference en Stop para evitar que el script ejecute cualquier otra declaración.

Otros consejos

El soporte de COM en PowerShell no es 100% confiable. Pero creo que el verdadero problema es el propio iTunes. La aplicación y el modelo COM no fueron diseñados, IMO, para este tipo de gestión. Dicho esto, podrías implementar una trampa en tu script. Si se produce una excepción, puede dejar el script en reposo durante unos segundos.

Parte de su problema podría estar en cómo se evalúa $ Track.name. Puede intentar forzarlo para que evalúe completamente el nombre usando $ ($ Track.name).

Otra cosa que podrías intentar es usar el parámetro -strict con tu comando de nuevo objeto /

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top