寻求更深入地了解 MS Windows 事件 - FileSystemWatcher 和计划任务

寻求更深入地了解 MS Windows 事件 - FileSystemWatcher 和计划任务

我面前有一个任务的上下文:我想在 WinServer2012 上创建一个计划任务,该计划任务由文件的最后写入日期更改生成的事件触发。

我手中有 Powershell 代码(感谢https://gallery.technet.microsoft.com/scriptcenter/Powershell-FileSystemWatche-dfd7084b)监视此类事件并回调特定操作,例如:

$folder = 'c:\temp' # Enter the root path you want to monitor. 
$filter = 'test.txt'  # You can enter a wildcard filter here. 
$fsw = New-Object IO.FileSystemWatcher $folder, $filter -Property  @{IncludeSubdirectories = $false;NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'} 

Register-ObjectEvent $fsw Changed -SourceIdentifier FileChanged -Action { 
  $name = $Event.SourceEventArgs.Name 
  $changeType = $Event.SourceEventArgs.ChangeType 
  $timeStamp = $Event.TimeGenerated 
  Write-Host "The file '$name' was $changeType at $timeStamp" -fore white 
}

这段代码似乎创建了一种生成此类事件的机制,并且还注册了一个回调来响应此类事件。这是正确的理解吗?还是不管怎样都会生成事件?当我查看 FileSystemWatcher 类的文档时,https://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher(v=vs.110).aspx,似乎文件更改通知在没有实例化此类的情况下存在。通知与事件不同吗?该类文档说它监视通知并引发事件。因此,这表明除非实例化此类,否则不会出现事件。这表明通知与事件不同。

在任务计划程序实用程序中,我可以创建一个由事件触发的任务,并且可以使用 3 个字段:日志、源和事件 ID 来标识我想要触发的事件。仔细查看日志选项,我发现它与事件查看器实用程序中可用的事件日志变体有些相似。是否所有事件都按照定义发送到特定日志?

我如何确定可用的不同日志、源和事件 ID 以及它们所指的内容?有任何文档吗?

Powershell 代码与我在任务计划程序中配置的触发器之间是否存在联系?也许触发器不能如此具体地监控单个文件的 LastWrite 更改,并且该任务会在各种文件系统事件上被过于频繁地调用。对于我手头的任务,最好的解决方案可能是在启动时运行 powershell 代码,但是,我确实在寻求对事件如何工作的更深入的理解。

感谢您的帮助。

答案1

Chris Lewis - Microsoft Premier Support 提供了这个极好的答案:

嗨,凯文,

我已将你的帖子收录其中,并回答了相关问题大胆的。如果您还有其他问题,或者我所说的任何内容需要澄清,请告诉我:

这段代码似乎创建了一种生成此类事件的机制,并且还注册了一个回调来响应此类事件。这是正确的理解吗?还是无论如何都会生成事件?

本文中提到的事件与来自 .NET 对象的委托调用有关。以下是一些相关文档:https://msdn.microsoft.com/en-us/library/edzehd2t(v=vs.110).aspx。如果没有任何委托订阅,则不会引发该事件。问题中的对象是 FileSystemWatcher,它是必不可少的包装类,可公开 ReadDirectoryChanges 的大部分功能。它的使用有很多注意事项,并且它是一个尽力而为的侦听器,因此必须预料到会错过事件。以下是我过去写的几篇博客文章,介绍了它的局限性以及使用它和不使用它的方法: https://blogs.msdn.microsoft.com/winsdk/2015/05/19/filesystemwatcher-follies/ https://blogs.msdn.microsoft.com/winsdk/2015/06/04/filesystemwatcher-fencingpart-1/ https://blogs.msdn.microsoft.com/winsdk/2015/09/15/filesystemwatcher-fencingpart-2/

当我查看 FileSystemWatcher 类的文档时,https://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher(v=vs.110).aspx,似乎文件更改通知在没有实例化此类的情况下存在。通知与事件不同吗?该类文档说它监视通知并引发事件。因此,这表明除非实例化此类,否则不会出现事件。这表明通知与事件不同。

是的,通知和事件是不同的。此上下文中的事件仍然指与上述相同的事物。通知是指来自文件系统的数据,用于向 ReadDirectoryChanges 的活动订阅者报告更改。如果没有人订阅或内核很忙(对于这种特定类型,它尽最大努力,这对于 API 通常来说并不常见),则不会有通知。如果没有订阅者,甚至不会在内存中生成数据。此外,如果特定类型的文件系统的驱动程序不支持该功能运行所需的 IOctl,则不会生成数据,但据我所知,目前所有驱动程序都支持该功能。

在任务计划程序实用程序中,我可以创建一个由事件触发的任务,并且可以使用 3 个字段:日志、源和事件 ID 来标识要触发的事件。仔细查看日志选项,我发现它与事件查看器实用程序中可用的事件日志变体有些相似。是否所有事件都按照定义发送到特定日志?

事件查看器中的事件(任务调度程序使用的事件)与 .NET 事件完全无关。不幸的是,没有可以合理触发的事件来跟踪文件更改(您可以让更改日志将所有内容写入事件日志,但如果您触发了它,系统速度会大幅降低,因为除非您有一个 NTFS 驱动器,除了您关心的一个文件之外几乎没有其他活动,否则需要一直使用如此多的资源来监视和检查不同进程的更改)。您可以让代码一直运行以进行监视,然后在发生时写入特定事件,如果您这样做,则可以触发任务调度程序以根据该事件运行。

我如何确定可用的不同日志、源和事件 ID 以及它们所指的内容?有相关文档吗?

**此信息适用于使用事件日志 API 的特定系统。坚持使用 C#/PowerShell,您可以运行代码来获取 ProviderMetadata。我本来想输入一些代码,但实际上这个 stackoverflow 帖子中有很多 PowerShell 代码示例,可以很好地回答这个问题:https://stackoverflow.com/questions/21012622/get-windows-event-provider-information**

Powershell 代码与我在任务计划程序中配置的触发器之间是否存在联系?也许触发器不能如此具体地监控单个文件的 LastWrite 更改,并且该任务会在各种文件系统事件上被过于频繁地调用。对于我手头的任务,最好的解决方案可能是在启动时运行 powershell 代码,但是,我确实在寻求对事件如何工作的更深入的理解。

不,Powershell 代码和任务调度程序触发器之间没有任何联系。您经常看到人们在 Powershell 中使用的另一种事件触发器是 WMI;您也不想使用它。它实际上只会不断轮询才能运行,这使得它效率极低。始终运行代码是实现此目的的最佳方式,您要么必须使用更改日志(它具有文件系统类型要求并需要编写更多自己的解析代码),要么将轮询和恢复功能添加到使用 FileSystemWatcher 的实现中,如博客文章中所述。但是,话虽如此,如果您还控制更改文件的软件,那么当人们尝试使用 FileSystemWatcher 来完成某件事时,通常会有一个更好的集成点。

此致,

克里斯


顺便说一句 - Chris 正在度假,没有时间在这里输入答案,但他允许我这样做。当然,他值得称赞。

相关内容