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

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

我认为你应该检查三个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,它们都必须以这种方式监视文件访问以隐藏用户/操作系统。

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

以下是.Net 4.0中Shell扩展编码的几个示例 。

列处理程序会在文件夹“打开”时通知您,甚至可以让您为每个文件(新的详细信息列)提供额外的数据。

查看FileSystemWatcher类。

我能想到的最接近的东西,可能对你有用,就是使用静态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. } 

您可以使用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

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

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