我正在编写一个脚本来查看任何新mp4文件的目录,然后使用HandBrake的CLI工具转换该文件。监视目录以进行更改的逻辑单独工作,但是如果我将一个大视频放入"观看"目录转换失败,因为它在文件有时间完成复制之前,一看到新文件就会启动。
我使用do until循环检查文件是否已锁定/下载,然后在文件解锁/可写时继续。该循环作为一个独立的脚本运行,但在文件系统观察器内部使用时,它将暂停,并且该行没有任何错误:
[System.IO.FileStream] $fs = $convertingFile.OpenWrite();
无论$ ErrorActionPreference =" SilentlyContinue"被注释掉了。我已经无法收集任何日志输出,以查看脚本停止使用Start-Transcript或Out-File的原因。
我应该如何最好地收集有关脚本一旦到达此行就停止的错误信息?
Bonus:为什么这个脚本不能提供错误信息?
$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 :(得分:0)
我认为,当您在非cmdlet代码中遇到问题时,您会发现$ErrorActionPreference
仅影响cmdlet级别的错误。为此,您可能需要try
/ catch
构造。
答案 1 :(得分: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)