FileSystemWatcher用于监视打开的文件夹/文件
本文关键字:文件夹 文件 用于 监视 FileSystemWatcher | 更新日期: 2023-09-27 17:58:18
我浏览了一下,但找不到任何关于我想要的信息,如果有其他帖子已经讨论过了,我很抱歉。
我正在寻求有关代码的帮助,这些代码将在其他人打开特定文件夹时或在打开该文件夹下的文件时监视该文件夹。在这一点上,我可以看到用户何时打开和修改任何文件,但如果他们只是打开文件来查看它,即使我添加LastAccessed,它也不会引发事件。如有任何信息或帮助,我们将不胜感激。
文件夹名称为C:''Junk
C#4.0中的代码:
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
public static void Run()
{
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = @"C:'";
watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
| NotifyFilters.FileName | NotifyFilters.DirectoryName;
watcher.Filter = "junk";
// Add event handlers.
watcher.Changed += new FileSystemEventHandler(OnChanged);
watcher.Created += new FileSystemEventHandler(OnChanged);
watcher.Deleted += new FileSystemEventHandler(OnChanged);
watcher.Renamed += new RenamedEventHandler(OnRenamed);
watcher.IncludeSubdirectories = true;
watcher.EnableRaisingEvents = true;
// Wait for the user to quit the program.
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);
}
即使我添加LastAccessed,它也不会引发事件。
因为NotifyFilters.LastAccessed
指定要检索该属性,而不是要订阅的事件。可用的事件有Changed
、Created
或Deleted
,它们都不能满足您的要求。
您应该看一下ReadDirectoryChangesW
Win32函数,这里有介绍。它可以被传递一个FILE_NOTIFY_CHANGE_LAST_ACCESS
标志,它似乎可以传递你想要的东西:
对监视目录或子树中文件的上次访问时间的任何更改都会导致返回更改通知等待操作。
编辑:忽略这一点,FileSystemWatcher
确实在内部将NotifyFilters.LastWrite
作为int 32传递给ReadDirectoryChangesW
,这与FILE_NOTIFY_CHANGE_LAST_ACCESS
相同。我试过了,这个功能仍然不会通知文件访问。
也许这是由以下原因引起的:
"上次访问时间"具有松散的粒度,只能保证时间精确到一小时以内。在Windows Vista中,我们禁用了对上次访问时间的更新,以提高NTFS性能。如果您使用的应用程序依赖于此值,则可以使用以下命令启用它:
fsutil behavior set disablelastaccess 0
您必须重新启动计算机才能使此更改生效。
如果在命令提示符下执行该操作,则可能会写入LastAccess
,并触发事件。我不会在我的SSD上尝试,也没有准备好虚拟机,但在Windows 7上,disablelastaccess
似乎是开箱即用的。
如果当你禁用该行为时,它仍然不起作用,请等待Raymond Chen(或他自己)的建议框出现,通常有一个非常合乎逻辑的解释来解释为什么文档似乎没有正确描述你遇到的行为
您还可以在循环中扫描目录,然后查看Files的LastAccessed属性。当用户打开某个文件时,您想做什么?
要获得访问文件路径,有一个微筛选器驱动程序的解决方案。您必须实现微筛选器驱动程序才能实现要求。
您应该设置
watcher.Path = @"C:'junk";
如果事件应该为所有文件触发,则删除watcher.Filter
行
使用Filter属性可以为匹配的文件设置通配符,例如*.txt
您真正需要的是NtQuerySystemInformation枚举和计时器,这样您就可以扫描目录并查看是否有任何文件打开。文件系统观察程序不会向您提供此信息
public void OnChanged(object sender, FileSystemEventArgs e)
{
string FileName = System.IO.Path.GetFileName(e.FullPath);
if(IsAvailable(System.IO.Path.Combine(RecievedPath,FileName)))
{
ProcessMessage(FileName);
}
}
private void ProcessMessage(string fileName)
{
try
{
File.Copy(System.IO.Path.Combine(RecievedPath,fileName), System.IO.Path.Combine(SentPath,fileName));
MessageBox.Show("File Copied");
}
catch (Exception)
{ }
}
private static bool IsAvailable(String filePath)
{
try
{
using (FileStream inputStream = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.None))
{
if (inputStream.Length > 0)
{
return true;
}
else
{
return false;
}
}
}
catch (Exception)
{
return false;
}
}
我只想添加几个单词和一个链接,感兴趣的用户可以从中开始。
FileSystemWatcher只用于监视被监视文件夹内发生的事情,但它不能监视和截获用户(或操作系统)正在做的事情。
例如,使用FSW(FileSystemWatcher),您可以监视文件/文件夹何时以某种方式创建、删除、重命名或更改,以及这些事件何时在操作完成后释放,而不是在此之前或期间。
简单的FSW无法知道用户是否正在从受监控的文件夹启动可执行文件,在这种情况下,它根本不会生成任何事件。
要在可执行文件启动前捕捉其启动时间(以及大量其他"事件"),并在将可执行文件的代码加载到内存之前执行一些操作,您需要在较低的(内核)级别编写一些东西,也就是说,您需要构建一个驱动程序,在特定情况下是一个(微筛选器)文件系统驱动程序。
这是一个很好的起点,开始了解基本的Minifilter Windows驱动程序:
https://learn.microsoft.com/en-us/windows-hardware/drivers/ifs/file-system-minifilter-drivers