在Windows中处理系统文件夹事件

时间:2011-09-20 02:55:12

标签: c# winapi event-handling filesystems

我正在编写一些C#代码,我需要检测应用程序运行时是否已打开Windows文件系统上的特定文件夹。有什么办法吗? WinAPI可能吗?

6 个答案:

答案 0 :(得分:2)

我认为你应该检查三个API:

FindFirstChangeNotification()http://msdn.microsoft.com/en-us/library/aa364417%28VS.85%29.aspx 这为您提供了一个句柄,您可以等待并用于查找特定文件,目录或目录树中文件的更改。它不会告诉您何时浏览目录,但它会告诉您何时保存,重命名文件等等。

SetWindowsHookEx()http://msdn.microsoft.com/en-us/library/ms644990%28v=VS.85%29.aspx 你可以设置它在任何数量的事件发生时给你一个回调 - 实际上我很肯定你可以在打开一个目录时得到这个回调,但它可能会非常困难,因为你将拦截消息探索者的窗口。因此,您将在调试期间重新启动。

Windows Shell http://msdn.microsoft.com/en-us/library/bb776778%28v=VS.85%29.aspx 如果这不够痛苦,你可以尝试编写一个shell程序。

如果您正在尝试编写rootkit,我想您不希望我破坏您的详细信息。如果你不是想写一个rootkit,我建议你仔细查看一下。有开源rootkit,它们基本上都必须以这种方式监视文件访问以隐藏用户/操作系统。

答案 1 :(得分:1)

使用Windows Shell Extensions。您可以使用Shell命名空间扩展来创建一个不存在(或隐藏真实文件夹)的“虚拟”文件夹,例如GAC(C:\ Windows \ assembly)

Here are several examples of Shell Extension coding in .Net 4.0

当文件夹“打开”时,Column Handler会通知你,甚至可以为每个文件提供额外的数据(新的详细信息列)。

答案 2 :(得分:0)

查看 FileSystemWatcher 类。

答案 3 :(得分:0)

我能想到的最接近的东西,可能对你有用,就是使用静态Directory类。它提供了确定上次访问文件或目录的方法。您可以设置BackgroundWorker来监视在指定的时间间隔内是否访问了目录。使用DateTime跟踪间隔的开始和结束,如果上次访问时间介于这些之间,则可以使用BackgroundWorker的ProgressChanged事件来通知应用程序。

 BackgroundWorker folderWorker = new BackgroundWorker();
 folderWorker.WorkerReportsProgress = true;
 folderWorker.WorkerSupportsCancellation = true;
 folderWorker.DoWork += FolderWorker_DoWork;
 folderWorker.ProgressChanged += FolderWorker_ProgressChanged;

 folderWorker.RunWorkerAsync();

 void FolderWorker_DoWork(object sender, DoWorkEventArgs e)
 {
      BackgroundWorker worker = (BackgroundWorker)sender;

      while(!worker.CancellationPending)
      {
           DateTime lastAccess = Directory.GetLastAccessTime(DIRECTORY_PATH);

           //Check to see if lastAccess falls between the last time the loop started
           //and came to end.
           if(/*your check*/)
           {
                object state;  //Modify this if you need to send back data.
                worker.ReportProgress(0, state);
           }
      }
 }

 void FolderWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
 {
      //Take action here from the worker.ReportProgress being invoked.
 }

答案 4 :(得分:0)

您可以使用FileSystemInfo的LastAccessProperty。但问题是它可以被缓存。

FileSystemInfo:http://msdn.microsoft.com/en-us/library/975xhcs9.aspx

LastAccessTime属性:http://msdn.microsoft.com/en-us/library/system.io.filesysteminfo.lastaccesstimeutc.aspx

如前所述,这可以预先缓存。

“如果从以下任何DirectoryInfo方法返回FileSystemInfo对象的当前实例,则预缓存LastAccessTimeUtc属性的值:

GetDirectories

的GetFiles

GetFileSystemInfos

EnumerateDirectories

EnumerateFiles

EnumerateFileSystemInfos

要获取最新值,请调用Refresh方法。“

因此调用Refresh方法,但由于Windows缓存该值,它仍然可能不是最新的。 (这是根据msdn doc“FileSystemInfo.Refresh从当前文件系统获取文件的快照。即使文件系统返回不正确或过时的信息,Refresh也无法更正底层文件系统。这可能发生在Windows 98等平台上。“ - 链接:http://msdn.microsoft.com/en-us/library/system.io.filesysteminfo.refresh.aspx

答案 5 :(得分:-2)

我认为唯一能够可靠地实现此目的的方法是监视当前正在运行的进程并密切关注新的Explorer.exe实例和/或新的Explorer.exe生成的线程(“在单独进程上运行每个窗口”设置)阻碍了这里。)

我承认我没有关于如何编码的线索,但这就是我想要的。