VSCode和Powershell:如何调试和跟踪Register ObjectEvent调用的代码



我遗漏了什么吗?

我可以用F5开始调试过程,但我不能结束它,而且我不能逐步完成代码或进行正常的调试。

我认为这是由于代码挂起Register ObjectEvent?

(正在监视文件系统事件……(

运行此代码并将调试器附加到正在发生的事情的方法是什么?

代码:

$folder_to_watch = 'C:UsersdemouserDownloads'
$file_name_filter = '*.aac'
# to archive .aac files
$destination = 'c:temptestarc'  
$DestinationDirMP3 = 'C:datapersonalhinative-mp3'
$Watcher = New-Object IO.FileSystemWatcher $folder_to_watch, $file_name_filter -Property @{ 
IncludeSubdirectories = $false
NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'
}
$VLCExe = 'C:Program FilesVideoLANVLCvlc.exe' 
$onCreated = Register-ObjectEvent $Watcher -EventName Created -SourceIdentifier FileCreated -Action {
$path = $Event.SourceEventArgs.FullPath
$name = $Event.SourceEventArgs.Name
$changeType = $Event.SourceEventArgs.ChangeType
$timeStamp = $Event.TimeGenerated
Write-Host "The file '$name' was $changeType at $timeStamp"
Write-Host $path
# File Checks
while (Test-LockedFile $path) {
Start-Sleep -Seconds .2
}
# Move File
Write-Host "moving $path to $destination"
Move-Item $path -Destination $destination -Force -Verbose
# build the path to the archived .aac file
$SourceFileName = Split-Path $path -Leaf
$DestinationAACwoQuotes = Join-Path $destination $SourceFileName
$DestinationAAC = "`"$DestinationAACwoQuotes`""
$MP3FileName = [System.IO.Path]::ChangeExtension($SourceFileName,".mp3")
$DestinationMP3woQuotes = Join-Path $DestinationDirMP3 $MP3FileName
$DestinationMP3 = "`"$DestinationMP3woQuotes`""
$VLCArgs = "-I dummy -vvv $DestinationAAC --sout=#transcode{acodec=mp3,ab=48,channels=2,samplerate=32000}:standard{access=file,mux=ts,dst=$DestinationMP3} vlc://quit"
Write-Host "args $VLCArgs"
Start-Process -FilePath $VLCExe -ArgumentList $VLCArgs

}

function Test-LockedFile {
param ([parameter(Mandatory=$true)][string]$Path)  
$oFile = New-Object System.IO.FileInfo $Path
if ((Test-Path -Path $Path) -eq $false)
{
return $false
}

try
{
$oStream = $oFile.Open([System.IO.FileMode]::Open, [System.IO.FileAccess]::ReadWrite, [System.IO.FileShare]::None)
if ($oStream)
{
$oStream.Close()
}
$false
}
catch
{
# file is locked by a process.
return $true
}
}

来自Register ObjectEvent的官方文档(注释部分(

事件、事件订阅和事件队列仅存在于当前会话中。如果关闭当前会话,则会丢弃事件队列,并取消事件订阅。

以上所有内容都属于您的会话,当进程退出时,会话将终止。即使它在其他地方,您的.netFileSystemWatcher也是该过程的一部分,并且在会话退出时立即终止。

现在,当您通过VSCode/ISE进行调试时,您的会话是预先创建的,并且在您退出脚本后不会终止,这允许您评估上次执行的变量。这也意味着您的订阅和事件回调以及关联的.net对象此时仍在内存中并处于活动状态。

也就是说,在脚本退出的那一刻,调试器也分离了。这也意味着,如果您不进行调试,只运行脚本,您的会话将在脚本执行后立即退出,因此,您的侦听器、事件回调和其他一切都将立即退出,而没有机会处理任何事情。

为了保持调试器的连接,能够调试,并使脚本在正常上下文中工作,您需要在一定程度上保持进程的活力。

确保这一点的常用方法是在脚本末尾添加一个循环。

# At the end of the script.
while ($true) {
Start-Sleep -Seconds 1
}

请注意,事件被提升到主线程,这意味着如果脚本处于休眠状态,则不会立即处理它。因此,在上面的例子中,如果在1秒的时间段内发生10个事件,那么当线程停止睡眠时,它们将同时被处理。

调试注意事项:为了处理调试CCD_ 2时已注册的事件错误。,您可以在Try / Catch / Finally块的Finally部分中添加清理代码。

try {
# At the end of the script... 
while ($true) {
Start-Sleep -Seconds 1
}    
}
catch {}
Finally {
# Work with CTRL + C exit too !
Unregister-Event -SourceIdentifier FileCreated 
}

参考文献:

注册ObjectEvent

最新更新