PowerShell中Register-ObjectEvent幽灵实例执行缓存Python脚本问题求助
问题描述
我用PowerShell的New-Object System.IO.FileSystemWatcher和Register-ObjectEvent监控指定共享文件夹\\ab\b\c,触发新文件创建事件时执行Python脚本,整个任务以服务用户账户作为计划任务运行。
最近修改了Python脚本,触发事件时能看到新逻辑的行为,但脚本日志里却还会出现已经删除的旧日志行,就像存在文件系统监视器的「幽灵」或缓存实例一样。
相关PowerShell代码如下:
$watcher = New-Object System.IO.FileSystemWatcher $watcher.Path = "\\ab\b\c" $watcher.Filter = "*.*" $watcher.EnableRaisingEvents = $true $action = { # call python script to do all the work $pythonPath = 'C:\a\b\c.py args' Start-Process "C:\Program Files (x86)\Python3\python.exe" -ArgumentList @($pythonPath) -NoNewWindow -PassThru -Wait -RedirectStandardError psstderr.txt -RedirectStandardOutput psstout.txt } Register-ObjectEvent $watcher "Created" -Action $action while ($true) { Start-Sleep 5 }
我尝试用Get-EventSubscriber和Get-FileSystemWatcher排查,但因为不在同一个会话里,没获取到任何信息;重启服务器也没能解决问题。怀疑是没关闭进程,但用Get-Process没发现运行中的Python进程。
简言之:事件触发时,文件系统监视器执行了机器上已经不存在的Python脚本缓存版本。
解决方法
彻底清理计划任务的残留会话
计划任务的服务账户会话可能未被正确终止,导致旧的FileSystemWatcher实例在后台持续运行:- 打开「任务计划程序」,找到对应的监控任务,先禁用并停止它。
- 打开「任务管理器」切换到「详细信息」标签,找到所有属于该服务账户的
powershell.exe进程,强制结束(注意不要误杀其他无关进程)。 - 等待1-2分钟后,重新启用并启动计划任务。
修改PowerShell脚本,添加实例唯一性与前置清理逻辑
在脚本启动时先清理可能存在的旧订阅与实例,避免重复注册:# 清理当前会话中同路径的旧监视器订阅与任务 Get-EventSubscriber | Where-Object { $_.SourceObject -is [System.IO.FileSystemWatcher] -and $_.SourceObject.Path -eq "\\ab\b\c" } | Unregister-Event -Force Get-Job | Where-Object { $_.Name -match "FileSystemWatcher" } | Remove-Job -Force # 创建新的监视器实例 $watcher = New-Object System.IO.FileSystemWatcher $watcher.Path = "\\ab\b\c" $watcher.Filter = "*.*" $watcher.EnableRaisingEvents = $true $action = { # 每次执行前校验脚本最新修改时间,确保执行的是最新版本 $pythonScriptPath = "C:\a\b\c.py" $scriptLastWrite = (Get-Item $pythonScriptPath).LastWriteTime Write-Host "Executing script modified at: $scriptLastWrite" $pythonExe = "C:\Program Files (x86)\Python3\python.exe" # 明确拆分脚本路径与参数,避免解析问题 Start-Process $pythonExe -ArgumentList @($pythonScriptPath, "args") -NoNewWindow -PassThru -Wait -RedirectStandardError "$PSScriptRoot\psstderr.txt" -RedirectStandardOutput "$PSScriptRoot\psstout.txt" } # 注册事件时指定唯一标识,方便后续排查 Register-ObjectEvent $watcher "Created" -Action $action -SourceIdentifier "FolderMonitor_ABBC" while ($true) { Start-Sleep 5 }清理Python字节码缓存
Python会生成.pyc字节码缓存文件,可能导致执行旧逻辑:- 进入Python脚本所在目录
C:\a\b\,删除所有.pyc文件或__pycache__文件夹。 - 修改PowerShell中的Python启动命令,强制禁用缓存:
Start-Process $pythonExe -ArgumentList @("-B", $pythonScriptPath, "args") ...-B参数会让Python不生成.pyc文件,每次直接读取原始.py脚本。
- 进入Python脚本所在目录
调整计划任务配置
打开计划任务的「设置」选项卡,勾选「如果任务已经在运行,则不启动新实例」,避免重复启动多个监视器进程。
内容的提问来源于stack exchange,提问作者maifosz
相关产品推荐
相关产品推荐

