7

我已经浏览过,但找不到任何关于我正在寻找的信息,如果有另一个帖子已经涵盖了这个,那么我道歉。

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

6 回答 6

2

即使我添加 LastAccessed,它也不会引发事件。

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

您应该查看此处ReadDirectoryChangesW记录的 Win32 函数。它可以传递一个标志,这似乎提供了你想要的东西:FILE_NOTIFY_CHANGE_LAST_ACCESS

对监视目录或子树中文件的最后访问时间的任何更改都会导致更改通知等待操作返回。

编辑:忽略这一点,FileSystemWatcher确实在内部传递NotifyFilters.LastWrite为 int 32,这与FILE_NOTIFY_CHANGE_LAST_ACCESS, to相同ReadDirectoryChangesW。然后该功能仍然不会通知文件访问,我已经尝试过了。

也许这是由这个引起的:

Last Access Time 具有松散的粒度,仅保证时间精确到一小时以内。在 Windows Vista 中,我们禁用了对上次访问时间的更新以提高 NTFS 性能。如果您正在使用依赖此值的应用程序,则可以使用以下命令启用它:

fsutil behavior set disablelastaccess 0

您必须重新启动计算机才能使此更改生效。

如果您在命令提示符下执行该操作,则可能LastAccess会写入该事件并触发该事件。我不打算在我的 SSD 上试用,也没有准备好 VM,但在 Windows 7 上disablelastaccess似乎是开箱即用的。

如果禁用该行为后仍然无法正常工作,请等待 Raymond Chen(或他自己)的建议箱出现,通常有一个非常合乎逻辑的解释来解释为什么文档似乎没有正确描述您遇到的行为。;-)

您也可以循环扫描目录并查看文件的 LastAccessed 属性。用户打开某个文件时,您想做什么?

于 2013-02-08T19:13:28.393 回答
1

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

于 2017-06-28T09:47:02.953 回答
0

what you really need is NtQuerySystemInformation enumeration and a timer, that way you can scan the directory and see if any of the files are open. the filesystemwatcher will not give you this info

于 2013-02-08T19:50:30.423 回答
0

你应该设置

watcher.Path = @"C:\junk";

watcher.Filter如果事件应该为所有文件触发,则删除行

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

于 2013-02-08T19:13:15.347 回答
0
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;
    }
}
于 2016-10-14T09:01:50.913 回答
0

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

我只想添加几句话和一个感兴趣的用户可以开始的链接。

FileSystemWatcher 仅用于监视受监视文件夹内发生的事情,但它无法监视和拦截用户(或操作系统)正在执行的操作。

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

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

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

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

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

于 2019-03-24T12:23:43.547 回答