2017-06-06 63 views
0

我正在編寫一個腳本,該腳本將監視任何新的mp4文件的目錄,然後使用HandBrake的CLI工具轉換該文件。監視目錄更改的邏輯本身是有效的,但是如果我將大視頻放入「已監視」目錄,轉換就會失敗,因爲只要文件有時間完成複製,它就會在啓動時看到新文件。無法收集停止Powershell腳本的錯誤信息

我正在使用do until循環來檢查文件是否鎖定/下載,然後一旦文件解鎖/寫入就繼續。循環可以作爲一個獨立的腳本,但在文件系統中使用時,守望者的腳本將沒有任何錯誤,停止在這條線:

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

不管出現這種情況,如果$ ErrorActionPreference =「SilentlyContinue」的評論出。我一直無法收集任何日誌輸出,以瞭解腳本使用啓動腳本或外部文件停止的原因。

我應該如何最好地收集有關爲什麼腳本一旦遇到此線路就停止的錯誤信息?

獎勵:爲什麼這個腳本不能提供錯誤信息?

$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只的cmdlet水平影響的錯誤,而你打非cmdlet的代碼有問題。爲此,您可能需要一個try/catch結構。

+0

我提高了你的答案,但不幸的是,我的聲譽先於我。我將使用try/catch來引發異常消息,並讓您知道結果! –

+0

我將「do while」循環轉換爲使用try/catch而不是if語句,並使用$ _。Exception.Message和$ _。Exception.ItemName來查看發生了什麼。當運行獨立腳本時,我通常會看到異常,但$ ErrorActionPreference會正常運行。 if語句是錯誤的方法......從這一點開始,我將使用try/catch/finally來更好地實現效果!感謝您的幫助。 =)我會發佈一個新的答案與這些細節和代碼,但仍然會推薦你的答案。 –

0

基於Burt_Harris的回答(請提供他對此答案的回答),我更改了「do while」循環,以便它使用try/catch而不是if/else語句。通過使用$ .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)