我浏览过但却无法找到有关我所寻求的任何信息,如果还有其他帖子已经过去,那么我道歉。
我正在寻找帮助代码,该代码将监视特定文件夹,以便在其他人打开文件夹时或打开所述文件夹下的文件时。此时我可以看到用户打开并修改任何文件的时间,但如果他们只是打开文件来查看它,即使我添加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函数,记录here。它可以通过一个FILE_NOTIFY_CHANGE_LAST_ACCESS
标志,这似乎提供了你想要的:
对监视目录或子树中文件的上次访问时间的任何更改都会导致更改通知等待操作返回。
编辑:忽略这一点,FileSystemWatcher
内部传递NotifyFilters.LastWrite
作为int 32,这与FILE_NOTIFY_CHANGE_LAST_ACCESS
相同,ReadDirectoryChangesW
。那个函数仍然没有通知文件访问,我试过了。
也许这是由this引起的:
上次访问时间具有松散的粒度,仅保证时间在一小时内准确。在Windows Vista中,我们禁用了对上次访问时间的更新以提高NTFS性能。如果您使用的是依赖于此值的应用程序,则可以使用以下命令启用它:
fsutil behavior set disablelastaccess 0
您必须重新启动计算机才能使此更改生效。
如果你在命令提示符下执行它,那么可能会写入LastAccess
并触发事件。我不会尝试使用我的SSD并且没有准备好VM,但是在Windows 7上,disablelastaccess
似乎是开箱即用的。
如果在禁用该行为时它仍然无效,请等待Raymond Chen的建议框(或他自己)过来,通常有一个非常合乎逻辑的解释,说明为什么文档似乎没有正确描述您遇到的行为。 ;-)
您也可以只在循环中扫描目录并查看Files的LastAccessed属性。当用户打开某个文件时你想做什么?
要获得On-Access文件路径,有一个minifilter驱动程序的解决方案。您必须实现minifilter驱动程序才能实现要求。
你真正需要的是NtQuerySystemInformation枚举和计时器,这样你就可以扫描目录并查看是否有任何文件是打开的。 filesystemwatcher不会给你这个信息
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;
}
}
Digvijay Rathore给出了一个答案,在我看来是唯一的好答案,即使有点太短。
我只想添加一些单词和一个感兴趣的用户可以开始的链接。
FileSystemWatcher仅用于监视受监视文件夹中发生的事情,但它无法监视和拦截用户(或操作系统)正在执行的操作。
例如,使用FSW(FileSystemWatcher),您可以监视何时以某种方式创建,删除,重命名或更改文件/文件夹,并在操作完成后释放这些事件,而不是在此之前或之后。
简单的FSW无法知道用户是否从受监视的文件夹中启动可执行文件,在这种情况下,它根本不会生成任何事件。
要在可执行文件启动之前捕获可执行文件(以及大量其他“事件”)并在可执行文件的代码加载到内存之前执行某些操作,您需要在较低(内核)级别编写一些内容,即您需要构建一个驱动程序,在这种特定情况下是一个(minifilter)文件系统驱动程序。
这是开始理解Minifilter Windows驱动程序基础的一个很好的起点:
https://docs.microsoft.com/en-us/windows-hardware/drivers/ifs/file-system-minifilter-drivers