FileSystemWatcher用于监视文件夹/文件打开

时间:2013-02-08 19:06:38

标签: c# .net wpf filesystemwatcher

我浏览过但却无法找到有关我所寻求内容的任何信息,如果还有其他帖子已经过去,那么我道歉。

我正在寻求帮助代码,该代码将监视特定文件夹,以便在其他人打开文件夹时或打开所述文件夹下的文件时。此时我可以看到用户打开并修改任何文件的时间,但如果他们只是打开文件来查看它,即使我添加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);
    }

6 个答案:

答案 0 :(得分:2)

  

即使我添加LastAccessed也不会抛出事件。

因为NotifyFilters.LastAccessed指定您希望检索该属性,而不是要订阅的事件。可用事件为ChangedCreatedDeleted,其中任何一项都不符合您的要求。

您应该查看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属性。当用户用户打开某个文件时,您想要做什么

答案 1 :(得分:1)

要获取On-Access文件路径,有一个minifilter驱动程序的解决方案。您必须实现minifilter驱动程序才能实现要求。

答案 2 :(得分:0)

你应该设置

watcher.Path = @"C:\junk";
如果要为所有文件触发事件,请

并删除watcher.Filter

使用Filter属性,您可以为匹配的文件设置通配符,例如*.txt

答案 3 :(得分:0)

您真正需要的是NtQuerySystemInformation枚举和计时器,这样您就可以扫描目录并查看是否有任何文件是打开的。 filesystemwatcher不会给你这个信息

答案 4 :(得分:0)

// Retrieve the type
#define DETAIL_TYPEOF_HEAD_(x , ...) REM x
#define DETAIL_TYPEOF_HEAD( args ) DETAIL_TYPEOF_HEAD_ args
#define DETAIL_TYPEOF_PROBE(...) (__VA_ARGS__),
#define DETAIL_TYPEOF(...) DETAIL_TYPEOF_HEAD((__VA_ARGS__))
#define TYPEOF(x) DETAIL_TYPEOF(DETAIL_TYPEOF_PROBE x,)

答案 5 :(得分:0)

Digvijay Rathore已经给出了答案,我认为这是唯一的好答案,即使有点太短。

我只想添加一些单词和一个链接,让感兴趣的用户可以开始。

FileSystemWatcher仅用于监视受监视文件夹中正在发生的事情,但不能监视和拦截用户(或操作系统)正在做什么。

例如,使用FSW(FileSystemWatcher),您可以监视何时以某种方式创建,删除,重命名或更改文件/文件夹,以及在完成操作后释放这些事件,而不是之前或之后。

简单的FSW无法知道用户是否正在从受监视的文件夹中启动可执行文件,在这种情况下,它根本不会产生任何事件。

要在可执行文件启动之前捕获其启动时间(以及大量其他“事件”),并在将可执行文件的代码加载到内存中之前进行一些操作,则需要编写较低(内核)级别的内容,也就是说,您需要构建一个驱动程序,在这种情况下,需要构建一个(微型过滤器)文件系统驱动程序。

这是开始了解Minifilter Windows驱动程序基础的好起点:

https://docs.microsoft.com/en-us/windows-hardware/drivers/ifs/file-system-minifilter-drivers