2017-06-06 3 views
0

Ich schreibe ein Skript, das ein Verzeichnis nach neuen mp4-Dateien durchsucht und anschließend die Datei mit dem CLI-Tool von HandBrake konvertiert. Die Logik, die das Verzeichnis nach Änderungen überwacht, funktioniert für sich selbst, aber wenn ich ein großes Video in das "überwachte" Verzeichnis verschiebe, schlägt die Konvertierung fehl, da es eine neue Datei anzeigt, bevor die Datei fertig kopiert werden kann.Fehlerinformationen vom angehaltenen Powershell-Skript können nicht erfasst werden.

Ich verwende eine do-up-Schleife, um zu prüfen, ob die Datei gesperrt/herunterladen und dann weiter, sobald die Datei entsperrt/schreibbar ist. Die Schleife arbeitet als Stand-alone-Skript, aber wenn sie innerhalb des Dateisystem-Beobachter das Skript verwendet es ohne Fehler auf dieser Linie anhalten wird:

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

Dies geschieht unabhängig davon, ob $ ErrorActionPreference = „SilentlyContinue“ kommentiert wird aus. Ich konnte keine Protokollausgabe erfassen, um festzustellen, warum das Skript mit Start-Transcript oder Out-File angehalten wurde.

Wie sollte ich am besten Fehlerinformationen darüber erhalten, warum das Skript anhält, sobald es diese Zeile erreicht?

Bonus: Warum könnte dieses Skript keine Fehlerinformationen liefern?

$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

Ihr Beitrag ist nicht wirklich eine klare Frage, hat aber mehrere Art impliziert. Ich habe einen Stich auf eine Antwort genommen, aber bitte einen Blick auf https://StackOverflow.com/Help/how-to-ask –

+0

Vielen Dank für Ihre Eingabe. Ich habe versucht, die Problembeschreibung neu zu schreiben und habe ein paar Fragen gestellt, die klarer sein sollten. –

Antwort

0

Ich glaube, Sie werden feststellen, dass $ErrorActionPreference nur Fehler auf der Ebene der Cmdlets auswirken, während Sie ein Problem in nicht-Cmdlets Code zu treffen. Dafür benötigen Sie wahrscheinlich ein try/catch Konstrukt.

+0

Ich habe Ihre Antwort aufgestockt, aber leider geht mir mein Ruf voraus. Ich werde den Versuch/Fang verwenden, um die Ausnahmebedingungsnachricht herauszuziehen und Ihnen die Ergebnisse mitzuteilen! –

+0

Ich konvertierte die "do while" -Schleife, um try/catch anstelle der if-Anweisung zu verwenden, und verwendete $ _. Exception.Message und $ _. Exception.ItemName, um zu sehen, was vor sich ging. Die Ausnahme ist das, was ich normalerweise sehen würde, wenn ich das Script alleine ausführen würde, aber die $ ErrorActionPreference würde normalerweise normal laufen. Die if-Anweisung war der falsche Ansatz ... Von diesem Punkt an werde ich versuchen/fangen/endlich besser zu wirken! Danke für Ihre Hilfe. =) Ich werde eine neue Antwort mit diesen Details & Code posten, werde aber trotzdem deine Antwort empfehlen. –

0

Basierend auf Burt_Harris 'Antwort (bitte upvote seine Antwort über diese), änderte ich die "do while" -Schleife, so dass es try/catch statt einer if/else-Anweisung verwenden würde. Mit $ .Exception.Message und $ .Exception.ItemName konnte ich besser verstehen, warum das Skript bei dieser bestimmten Zeile angehalten wurde.

Arbeitscode:

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) 
Verwandte Themen