2017-06-06 11 views
0

新しいmp4ファイルのディレクトリを監視し、HandBrakeのCLIツールを使用してファイルを変換するスクリプトを作成しています。ディレクトリの変更を監視するロジックは単独で機能しますが、大きなファイルを「監視」ディレクトリにドロップすると、ファイルのコピーが完了する前に新しいファイルが表示されるとすぐに変換が失敗します。Powershellスクリプトを停止してエラー情報を収集できません

私はdo untilループを使ってファイルがロックされているかどうかをチェックしています。ループは、スタンドアロンスクリプトとして動作しますが、ファイルシステムウォッチャーの内部で使用する場合には、このライン上のエラーなしに停止するスクリプト:$ ErrorActionPreference =「SilentlyContinueという」がコメントされている場合

[System.IO.FileStream] $fs = $convertingFile.OpenWrite();

はこれに関係なく発生しますでる。私は、スクリプトがStart-TranscriptまたはOut-Fileを使用して停止している理由を確認するために、ログ出力を収集できませんでした。

この行にヒットしたスクリプトが停止する理由についてのエラー情報をどのように収集するのが最適でしょうか?

ボーナス:なぜこのスクリプトでエラー情報が表示されないのですか?

$ErrorActionPreference = "SilentlyContinue" 

    function Start-FileSystemWatcher { 

     [CmdletBinding()] 
     param(
     [Parameter()] 
     [string]$Path, 
     [Parameter()] 
     [ValidateSet('Changed','Created','Deleted','Renamed')] 
     [string[]]$EventName, 
     [Parameter()] 
     [string]$Filter, 
     [Parameter()] 
     [System.IO.NotifyFilters]$NotifyFilter, 
     [Parameter()] 
     [switch]$Recurse, 
     [Parameter()] 
     [scriptblock]$Action 
    ) 

     #region Build FileSystemWatcher 

     $FileSystemWatcher = New-Object System.IO.FileSystemWatcher 
     if (-not $PSBoundParameters.ContainsKey('Path')) { 
     $Path = $PWD 
     } 
     $FileSystemWatcher.Path = $Path 
     if ($PSBoundParameters.ContainsKey('Filter')) { 
     $FileSystemWatcher.Filter = $Filter 
     } 

     if ($PSBoundParameters.ContainsKey('NotifyFilter')) { 
     $FileSystemWatcher.NotifyFilter = $NotifyFilter 
     } 

     if ($PSBoundParameters.ContainsKey('Recurse')) { 
     $FileSystemWatcher.IncludeSubdirectories = $True 
     } 

     if (-not $PSBoundParameters.ContainsKey('EventName')) { 
     $EventName = 'Changed','Created','Deleted','Renamed' 
     } 

     if (-not $PSBoundParameters.ContainsKey('Action')) { 
     $Action = { 
      switch ($Event.SourceEventArgs.ChangeType) { 
      'Renamed' { 
       $Object = "{0} was {1} to {2} at {3}" -f $Event.SourceArgs[-1].OldFullPath, 
       $Event.SourceEventArgs.ChangeType, 
       $Event.SourceArgs[-1].FullPath, 
       $Event.TimeGenerated 
      } 

      Default { 
       $Object = "{0} was {1} at {2}" -f $Event.SourceEventArgs.FullPath, 
       $Event.SourceEventArgs.ChangeType, 
       $Event.TimeGenerated 
      } 
      } 

      $WriteHostParams = @{ 
      ForegroundColor = 'Green' 
      BackgroundColor = 'Black' 
      Object = $Object 
      } 

      Write-Host @WriteHostParams 
     } 

     } 

     $ObjectEventParams = @{ 
     InputObject = $FileSystemWatcher 
     Action = $Action 

     } 

     foreach ($Item in $EventName) { 
     $ObjectEventParams.EventName = $Item 
     $ObjectEventParams.SourceIdentifier = "File.$($Item)" 
     Write-Verbose "Starting watcher for Event: $($Item)" 
     $Null = Register-ObjectEvent @ObjectEventParams 
     } 

    } 

    $FileSystemWatcherParams = @{ 
     Path = 'X:\share\scripts\ps\converter\input' 
     Recurse = $True 
     NotifyFilter = 'FileName' 
     Verbose = $True 
     Action = { 
     $Item = Get-Item $Event.SourceEventArgs.FullPath 
     $WriteHostParams = @{ 
      ForegroundColor = 'Green' 
      BackgroundColor = 'Black' 
     } 

     $inputFile = "${PWD}\input\$($Item.Name)".trim() 
     $outputFile = "${PWD}\output\$($Item.Name)".trim() 
     $logFile = "${PWD}\log\$($Item.Name).txt" 
     $testLogFile = "${PWD}\log\$($Item.Name)(t).txt" 

     function mp4-Func { 
      Start-Transcript -path $logFile 
      Write-Host "New mp4 file detected..." 
      $convertingFile = New-Object -TypeName System.IO.FileInfo -ArgumentList $inputFile 
      $locked = 1 
      do { 
      [System.IO.FileStream] $fs = $convertingFile.OpenWrite(); 
      if (!$?) { 
       Write-Host "Can't convert yet, file appears to be loading..." 
       sleep 2 
      } 
      else { 
       $fs.Dispose() 
       $locked = 0 
      } 
      } until ($locked -eq 0) 

      Write-Host "File unlocked and ready for conversion." 
      HandBrake 
      Stop-Transcript 
      $WriteHostParams.Object = "Finished converting: $($Item.Name)" 
     } 

     function HandBrake { 
      .\HandBrakeCLI.exe --input "$inputFile" ` 
          --output "$outputFile" ` 
          --format av_mp4 ` 
          --encoder x264 ` 
          --vb 1700 ` 
          --two-pass ` 
          --aencoder copy:aac ` 
          --ab 320 ` 
          --arate 48 ` 
          --mixdown stereo 
     } 

     switch -regex ($Item.Extension) { 
      '\.mp4' { mp4-Func } 
     } 

     Write-Host @WriteHostParams 
     } 

    } 
    @('Created') | ForEach-Object { 
     $FileSystemWatcherParams.EventName = $_ 
     Start-FileSystemWatcher @FileSystemWatcherParams 
    } 
+0

あなたの投稿は本当に明確な質問ではありませんが、暗示のいくつかの並べ替えを持っています。私は答えで刺すようですが、https://stackoverflow.com/help/how-to-askを見てください –

+0

ありがとうございます。私は問題の説明を書き直そうとしましたが、より明確にすべきいくつかの質問を提供しました。 –

答えて

0

私はあなたが非コマンドレットのコードで問題を叩きながら$ErrorActionPreferenceのみ、コマンドレットのレベルでエラーに影響を与えることを見つけると思います。そのためには、おそらくtry/catch構成が必要です。

+0

私はあなたの答えをupvotedしかし、残念ながら、私の評判は私の前にある。 try/catchを使用して例外メッセージを取り出し、結果をお知らせします。 –

+0

"do while"ループをif文ではなくtry/catchを使用するように変換し、$ _。Exception.Messageと$ _。Exception.ItemNameを使用して何が起こっていたのかを確認しました。例外は、スタンドアロンのスクリプトを実行しているときに普通に見えるものですが、$ ErrorActionPreferenceはそれによって正常にロールバックします。 ifステートメントは間違ったアプローチでした...この時点から、try/catch/finallyを使用してより効果的に使用します。ご協力ありがとうございました。 =)私はこれらの詳細とコードを使って新しい回答を投稿しますが、依然としてあなたの答えを推薦します。 –

0

Burt_Harrisの回答(この回答をアップしてください)では、if/else文ではなくtry/catchを使用するようにdo whileループを変更しました。 $ .Exception.Messageと$を使用することによって.Exception.ItemNameスクリプトがその特定の行で停止していた理由をよりよく理解することができました。

の作業コード:

Do { 
    Try { 
     [System.IO.FileStream] $fs = $convertingFile.OpenWrite() 
     $fs.Dispose() 
     $locked = 0 
    } 
    Catch { 
     $ErrorMessage = $_.Exception.Message 
     $FailedItem = $_.Exception.ItemName 
     Write-Host $ErrorMessage 
     Write-Host $FailedItem 
     Write-Host "Can't convert yet, file appears to be loading..." 
     sleep 5 
     continue 
    } 
    } until ($locked -eq 0) 
関連する問題