无法收集停止Powershell脚本的错误信息

问题描述:

我正在编写一个脚本,该脚本将监视任何新的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://*.com/help/how-to-ask –

+0

感谢您的意见。我试图重写问题描述,并提供了一些应该更清楚的问题。 –

我想你会发现,$ErrorActionPreference只的cmdlet水平影响的错误,而你打非cmdlet的代码有问题。为此,您可能需要一个try/catch结构。

+0

我提高了你的答案,但不幸的是,我的声誉先于我。我将使用try/catch来引发异常消息,并让您知道结果! –

+0

我将“do while”循环转换为使用try/catch而不是if语句,并使用$ _。Exception.Message和$ _。Exception.ItemName来查看发生了什么。当运行独立脚本时,我通常会看到异常,但$ ErrorActionPreference会正常运行。 if语句是错误的方法......从这一点开始,我将使用try/catch/finally来更好地实现效果!感谢您的帮助。 =)我会发布一个新的答案与这些细节和代码,但仍然会推荐你的答案。 –

基于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)