Pergunta

Estou usando o PowerShell para automatizar o iTunes, mas encontrar o tratamento de erros / aguardando com manipulação de objetos para ser abaixo do ideal.

código Exemplo

#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 

Vá para o iTunes e fazer algo que torna aparecer uma mensagem - no meu caso eu ir para o Party Shuffle e fico com uma faixa "Party Shuffle automaticamente blá blá ...." com um "Não mostrar" mensagem .

Neste ponto, se executar o script vai fazer isso várias vezes:

+      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

Se você esperou até que você tivesse uma caixa de diálogo antes de executar o exemplo, então em vez disso você vai ter isso várias vezes:

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

Isso vai ser porque o identificador $ Biblioteca é inválido.

Se o meu exemplo foi fazendo algo importante - como converter faixas e, em seguida, apagar os antigos, não lidar com o erro corretamente poderia ser fatal para as faixas no iTunes. Eu quero endurecer-se o código para que ele lida com iTunes estar ocupado e silenciosamente repetir até que tenha sucesso. Alguma sugestão?

Foi útil?

Solução

Aqui está uma função para operações de repetição, fazendo uma pausa entre falhas:

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 o primeiro erro no seu exemplo, você poderia alterar o loop foreach interior como esta:

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

Este utiliza os valores padrão para $wait e $maxRetries, por isso vai tentar $Library.search chamada 100 vezes, esperando 2 segundos entre cada tentativa. Se todas as tentativas falharem, o último erro irá propagar para o escopo externo. Você pode definir $ErrorActionPreference para Stop para impedir que o script de executar quaisquer outras declarações.

Outras dicas

suporte COM no PowerShell não é 100% confiável. Mas eu acho que a verdadeira questão é próprio iTunes. O modelo de aplicação e COM não foi projetado, IMO, para este tipo de gestão. Dito isto, você poderia implementar uma armadilha em seu script. Se uma exceção é lançada, você poderia ter o sono de script por alguns segundos.

Parte do seu problema pode ser na forma como $ Track.name está sendo avaliada. Você poderia tentar forçá-lo a avaliar completamente o nome usando $ ($ Track.name).

Uma outra coisa que você pode tentar é usar o parâmetro -strict com o seu novo objeto de comando /

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top