当Windows系统中的目录发生更改时,我需要立即通知一个程序。
是否有一种方法可以在更改发生时执行一个程序?
我不是C/C++/.NET程序员,所以如果我能够设置一些东西来触发批处理文件,那就太理想了。
当Windows系统中的目录发生更改时,我需要立即通知一个程序。
是否有一种方法可以在更改发生时执行一个程序?
我不是C/C++/.NET程序员,所以如果我能够设置一些东西来触发批处理文件,那就太理想了。
使用类似下面的FileSystemWatcher来创建一个WatcherCreated事件。
我使用这个方法创建了一个Windows服务,用于监视一个网络文件夹,并在新文件到达时发送电子邮件给指定的组。
// Declare a new FILESYSTEMWATCHER
protected FileSystemWatcher watcher;
string pathToFolder = @"YourDesired Path Here";
// Initialize the New FILESYSTEMWATCHER
watcher = new FileSystemWatcher {Path = pathToFolder, IncludeSubdirectories = true, Filter = "*.*"};
watcher.EnableRaisingEvents = true;
watcher.Created += new FileSystemEventHandler(WatcherCreated);
void WatcherCreated(object source , FileSystemEventArgs e)
{
//Code goes here for when a new file is detected
}
FileSystemWatcher是正确的选择,但以前FileSystemWatcher只能一次处理“几个”更改。这是因为操作系统缓冲区的原因。实际上,每当复制许多小文件时,保存已更改文件名称的缓冲区就会被溢出。这种缓冲区不是跟踪最近更改的正确方式,因为操作系统必须停止写入以防止溢出。
Microsoft提供了其他设施(编辑:如更改日志),以真正捕获所有更改。本质上,这些设施是备份系统使用的,记录的事件非常复杂,并且文档化非常差。
一个简单的测试是生成大量小文件,看它们是否都由FileSystemWatcher报告。如果你有问题,我建议你绕过整个问题,在定时间隔内扫描文件系统进行更改。
我在搜索文件系统活动监控的方法时找到了这个页面。我参考了Refracted Paladin的帖子以及他分享的FileSystemWatcher,并编写了一个快速而简单的C#实现:
using System;
using System.IO;
namespace Folderwatch
{
class Program
{
static void Main(string[] args)
{
//Based on https://dev59.com/MnRA5IYBdhLWcg3w_C8w#27512511
//and http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.aspx
string pathToFolder = string.Empty;
string filterPath = string.Empty;
const string USAGE = "USAGE: Folderwatch.exe PATH FILTER \n\n e.g.:\n\n Folderwatch.exe c:\\windows *.dll";
try
{
pathToFolder = args[0];
}
catch (Exception)
{
Console.WriteLine("Invalid path!");
Console.WriteLine(USAGE);
return;
}
try
{
filterPath = args[1];
}
catch (Exception)
{
Console.WriteLine("Invalid filter!");
Console.WriteLine(USAGE);
return;
}
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = pathToFolder;
watcher.Filter = filterPath;
watcher.NotifyFilter = NotifyFilters.Attributes | NotifyFilters.CreationTime |
NotifyFilters.DirectoryName | NotifyFilters.FileName | NotifyFilters.LastAccess |
NotifyFilters.LastWrite | NotifyFilters.Security | NotifyFilters.Size;
// Add event handlers.
watcher.Changed += new FileSystemEventHandler(OnChanged);
watcher.Created += new FileSystemEventHandler(OnChanged);
watcher.Deleted += new FileSystemEventHandler(OnChanged);
watcher.Renamed += new RenamedEventHandler(OnRenamed);
// Begin watching.
watcher.EnableRaisingEvents = true;
// Wait for the user to quit the program.
Console.WriteLine("Monitoring File System Activity on {0}.", pathToFolder);
Console.WriteLine("Press \'q\' to quit the sample.");
while (Console.Read() != 'q') ;
}
// Define the event handlers.
private static void OnChanged(object source, FileSystemEventArgs e)
{
// Specify what is done when a file is changed, created, or deleted.
Console.WriteLine("File: " + e.FullPath + " " + e.ChangeType);
}
private static void OnRenamed(object source, RenamedEventArgs e)
{
// Specify what is done when a file is renamed.
Console.WriteLine("File: {0} renamed to {1}", e.OldFullPath, e.FullPath);
}
}
}
要使用这个功能,需要下载Visual Studio(Express版本就可以)。然后创建一个名为Folderwatch的新C#控制台应用程序,并将我的代码复制粘贴到Program.cs中。
作为替代方案,您可以使用Sys Internals Process Monitor:Process Monitor。它可以监视文件系统和更多内容。
FileSystemWatcher
是最简单的方法。ReadDirectoryChangesW
相对较难使用(需要了解完成端口)。FileSystemWatcher
代码后,我发现以下页面有一些类似但不完全相同的替代方案,可以解决FileSystemWatcher
的缺陷(也在一些答案中提到):
https://github.com/theXappy/FileSystemWatcherAlts
以下是针对每种情况哪种替代方案更好的比较表,底部有一个简单易懂的通用规则,解释了在哪种情况下使用哪种替代方案:https://github.com/theXappy/FileSystemWatcherAlts/blob/master/AltComparison.md
它很容易实现或修改。如果您的项目已经使用了FileSytemWatcher
,那么您只需要简单地更改这个:
FileSystemWatcher sysMonitor = new FileSystemWatcher(@"C:\");
对于以下任何一个:
IFileSystemWatcher sysMonitor = new FileSystemRefreshableWatcher(@"C:\");
IFileSystemWatcher sysMonitor = new FileSystemAutoRefreshingWatcher(@"C:\");
IFileSystemWatcher sysMonitor = new FileSystemPoller(pollingInterval: 500,path: @"C:\");
IFileSystemWatcher sysMonitor = new FileSystemOverseer(pollingInterval: 500, path: @"C:\");