FileSystemWatcher监听日志文件变更时无事件触发,求解决方案
问题描述
我尝试用FileSystemWatcher监听日志文件的变更,触发时执行命令。在记事本中保存文件时功能正常,但实际写入日志的应用程序操作时完全无效。我看到过相关说法,这类问题可能是因为应用程序采用了“创建含新数据的日志副本→删除原文件→重命名副本”的更新方式,所以我尝试监听删除、创建和重命名事件,但依然没效果。
我使用的是FileSystemWatcher的派生类(因业务需求必须为派生类,其他功能不在本次讨论范围内):
class LogWatcher : System.IO.FileSystemWatcher { [System.Management.Automation.Job[]] $Event [string] $LogName = 'Endpointlog.txt' [string] $LogFolder = ('C:\Users\' + $env:USERNAME + '\AppData\Roaming\<pathtologfolder>') LogWatcher () : base($this.LogFolder, $this.LogName) { $this.Event = (new-object System.Management.Automation.Job[] 4) $this.EnableRaisingEvents = $true; $fsaction = { param ( [System.Object] $sender, [System.IO.FileSystemEventArgs] $e ) $sender | fl $e | fl } $rnaction = { param ( [System.Object] $sender, [System.IO.renamedEventArgs] $e ) $sender | fl $e | fl } $this.NotifyFilter =[System.IO.NotifyFilters]::Attributes, [System.IO.NotifyFilters]::CreationTime, [System.IO.NotifyFilters]::DirectoryName, [System.IO.NotifyFilters]::FileName, [System.IO.NotifyFilters]::LastAccess, [System.IO.NotifyFilters]::LastWrite, [System.IO.NotifyFilters]::Security, [System.IO.NotifyFilters]::Size $this.Event[0] = register-ObjectEvent -InputObject $this -EventName changed -Action $fsaction $this.Event[1] = register-ObjectEvent -InputObject $this -EventName created -Action $fsaction $this.Event[2] = register-ObjectEvent -InputObject $this -EventName deleted -Action $fsaction $this.Event[3] = register-ObjectEvent -InputObject $this -EventName renamed -Action $rnaction } }
初始化代码:
$lw = [LogWatcher]::new();
日志文件每几秒更新一次,我预期$lw.Event中至少有一个Job处于运行状态而非“未启动”,但只有用记事本打开并保存(此时记事本提示“另存为”而非直接保存)时,才有一个Job状态变化。我还是认为问题出在文件被复制、删除并重命名的操作上,请问有没有办法捕获这类操作的事件?
解决方案
- 监听整个日志目录:原代码绑定的是单个文件,当文件被删除重建后,监听句柄会失效。改为监听整个日志目录(构造函数中只传入目录路径,或者将
Filter设为目标日志文件名),这样无论文件被删除、创建还是重命名,都能捕获到对应事件。 - 优化事件监听逻辑:
- 在
Created事件触发时,检查新文件的名称是否为目标日志文件,确认后再执行后续操作; - 当
Deleted事件触发且涉及目标文件时,记录该动作,后续结合Renamed或Created事件判断完整的更新流程。
- 在
- 增大事件缓冲区:如果日志更新频繁,
FileSystemWatcher的默认缓冲区可能溢出导致丢事件。可以在构造函数中添加$this.InternalBufferSize = 65536(最大值为64KB),提升缓冲区容量。 - 重新绑定失效监听:当捕获到目标文件被删除的事件后,重新注册针对该文件的
Changed事件监听,避免原监听失效后无法捕获后续变更。 - 搭配轮询兜底:如果
FileSystemWatcher仍不稳定,可添加定时轮询逻辑,定期检查日志文件的最后修改时间或大小,当检测到变化时执行命令。这种方式稳定性更高,适合对可靠性要求高的场景。
内容的提问来源于stack exchange,提问作者Mason Kerr
相关产品推荐
相关产品推荐

