提问人:Mason Kerr 提问时间:9/27/2023 更新时间:9/29/2023 访问量:35
找不到日志文件更改时引发的事件
Unable to find events being raised when log file changed
问:
我尝试用于监视文件并检查更改,当发生更改时,它应该运行 aa 命令,这在我将文件保存在记事本中时有效,但不是从制作日志文件的实际应用程序中。
我过去看到过帖子说,这可能是由于应用程序创建了添加了新数据的日志副本,然后删除了原始数据并重命名了副本,所以我尝试查找删除、创建和重命名事件,但仍然一无所获。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
Not Started
Job
有什么方法可以在进行这些切换时触发任何事件?
答:
事件的 Action 块在不同的范围内运行,其中生成的所有输出都捕获在 .
每个 PSEventJob
的 Output 属性。例如,on index 将显示引发的事件捕获的所有输出、事件的索引等:.Output
0
Changed
1
Created
$lw.Event[0].Output
但是,如果您正在进行故障排除,则使用起来要容易得多,然后输出将直接发送到控制台(也可以):Out-Host
Write-Host
$fsaction = {
$Sender | Format-List | Out-Host
$EventArgs | Format-List | Out-Host
}
这里值得注意的是,在 PowerShell 中,并且是自动变量,无需声明它们。$Sender
$EventArgs
我也对你的班级做了一些更改,可能会帮助你简化事情:
class LogWatcher : System.IO.FileSystemWatcher {
[System.Management.Automation.Job[]] $Event
[string] $LogName
[string] $LogFolder
LogWatcher([string] $folderPath, [string] $fileName) : base($folderPath, $fileName) {
$this.LogFolder = $folderPath
$this.LogName = $fileName
$this.EnableRaisingEvents = $true
# if you want to target all possibilities, this is easier ;)
$this.NotifyFilter = [enum]::GetValues([System.IO.NotifyFilters])
$this.Event = 'Changed', 'Created', 'Deleted', 'Renamed' | ForEach-Object {
Register-ObjectEvent -InputObject $this -EventName $_ -Action {
$Sender | Format-List | Out-Host
$EventArgs | Format-List | Out-Host
# this is so that your watcher can keep track of the new file
# instead of watching a file that no longer exists
if ($EventArgs.ChangeType -eq 'Renamed') {
$sender.LogName = $sender.Filter = $EventArgs.Name
}
}
}
}
}
现在进行测试时,这应该在 Windows PowerShell 5.1 和 PowerShell 7+ 中都能正常工作。您应该看到所有事件都已引发。
$watcher = [LogWatcher]::new($pwd.Path, 'testingwatcher.txt')
'Creating File...'
Start-Sleep 1
$file = New-Item 'testingwatcher.txt' -Force
'Changing File...'
Start-Sleep 1
$file.LastWriteTime = [datetime]::Today
'Renaming File...'
Start-Sleep 1
$file = $file | Rename-Item -NewName 'ihaveanewname.txt' -PassThru
'Deleting File...'
Start-Sleep 1
$file.Delete()
# Cleanup - probably your class should implement IDisposable ;)
$watcher.Event.Name | Unregister-Event -SourceIdentifier { $_ }
评论