7

在 Windows 中,是否有一种简单的方法来判断文件夹是否有已更改的子文件?

我验证了,当子文件更改时,文件夹上的最后修改日期不会更新。

我可以设置一个注册表项来修改此行为吗?

如果重要的话,我使用的是 NTFS 卷。

我最终希望从 C++ 程序中获得这种能力。

递归扫描整个目录对我不起作用,因为该文件夹太大了。

更新:我真的需要一种方法来做到这一点,而无需在更改发生时运行进程。所以安装文件系统观察器对我来说不是最佳选择。

Update2:存档位也将不起作用,因为它与上次修改日期有相同的问题。将设置文件的存档位,但不会设置文件夹。

4

8 回答 8

6

这篇文章 应该有所帮助。基本上,您创建一个或多个通知对象,例如:

处理 dwChangeHandles[2];
dwChangeHandles[0] = FindFirstChangeNotification(
      lpDir, // 观察目录
      FALSE, // 不看子树
      FILE_NOTIFY_CHANGE_FILE_NAME); // 观察文件名变化

   如果(dwChangeHandles[0] == INVALID_HANDLE_VALUE)
   {
     printf("\n 错误:FindFirstChangeNotification 函数失败。\n");
     ExitProcess(GetLastError());
   }

// 观察子树目录的创建和删除。  
   dwChangeHandles[1] = FindFirstChangeNotification(
      lpDrive, // 观看的目录
      TRUE, // 观察子树
      FILE_NOTIFY_CHANGE_DIR_NAME); // 观察目录名称变化

   if (dwChangeHandles[1] == INVALID_HANDLE_VALUE)
   {
     printf("\n 错误:FindFirstChangeNotification 函数失败。\n");
     ExitProcess(GetLastError());
   }

然后等待通知:

而(真)
   {
   // 等待通知。
      printf("\n等待通知...\n");

      DWORD dwWaitStatus = WaitForMultipleObjects(2, dwChangeHandles,
         错误,无限);

      开关(dwWaitStatus)
      {
         案例 WAIT_OBJECT_0:

         // 在目录中创建、重命名或删除文件。
         // 重启通知。
             if ( FindNextChangeNotification(dwChangeHandles[0]) == FALSE )
             {
               printf("\n 错误:FindNextChangeNotification 函数失败。\n");
               ExitProcess(GetLastError());
             }
             休息;

         案例 WAIT_OBJECT_0 + 1:

         // 重启通知。
             if (FindNextChangeNotification(dwChangeHandles[1]) == FALSE)
             {
               printf("\n 错误:FindNextChangeNotification 函数失败。\n");
               ExitProcess(GetLastError());
             }
             休息;

         案例WAIT_TIMEOUT:

         // 发生超时。如果其他一些价值会发生这种情况
         // 而不是在等待调用中使用 INFINITE 并且不会发生任何更改。
         // 在单线程环境中,您可能不需要
         // 无限等待。

            printf("\n超时时间没有变化。\n");
            休息;

         默认:
            printf("\n 错误:未处理的 dwWaitStatus.\n");
            ExitProcess(GetLastError());
            休息;
      }
   }
}
于 2008-09-11T14:54:57.993 回答
3

这可能是矫枉过正,但MS的IFS 套件或 OSR 的FDDK可能是一个替代方案。创建您自己的文件系统过滤器驱动程序,对文件系统的所有更改进行简单监控。

于 2008-12-02T20:11:42.213 回答
2

读取目录更改W

这篇 CodeProject 文章中的一些优秀示例代码

于 2008-10-03T20:45:39.313 回答
1

如果您在更改发生时无法运行进程,那么除了扫描文件系统并检查修改日期/时间之外,您无能为力。但是,这需要您存储每个文件的最后日期/时间并进行比较。

您可以通过使用存档位来加快速度(尽管它可能会弄乱您的备份软件,因此请谨慎操作)。

存档位是存在于许多计算机文件系统中的文件属性,特别是 FAT、FAT32 和 NTFS。归档位的目的是跟踪文件的增量更改以进行备份,也称为归档。

由于归档位是二进制位,它要么是 1 要么是 0,或者在这种情况下更频繁地称为设置 (1) 和清除 (0)。每当文件被创建、移动、重命名或以任何方式修改时,操作系统都会设置存档位。因此,归档位表示自上次备份以来的两种状态之一:“已更改”和“未更改”。

归档位不受简单地读取文件的影响。复制文件时,原始文件的存档位不受影响,但副本的存档位将在制作副本时设置。

所以这个过程是:

  1. 清除所有文件的存档位
  2. 让文件系统随时间变化
  3. 扫描所有文件 - 任何设置了存档位的文件都已更改

这将消除您的程序保持状态的需要,并且由于您只检查目录条目(存储位的位置)并且它们是集群的,因此它应该非常非常快。

但是,如果您可以在更改期间运行进程,那么您将需要查看FileSystemWatcher类。这是一个如何使用它的示例。

它也存在于.NET中(对于此类问题的未来搜索者)

也许您可以让机器上运行一个进程来监视更改并创建一个文件供您稍后阅读。

-亚当

于 2008-09-11T14:35:05.403 回答
1

也许您可以将 NTFS 5 Change Journal 与 DeviceIoControl 一起使用,如此处所述

于 2008-09-11T16:17:26.140 回答
0

如果您不反对使用 .NET,那么FileSystemWatcher类会很容易地为您处理这个问题。

于 2008-09-11T14:36:28.240 回答
0

没有什么容易的 - 如果您有一个正在运行的应用程序,您可以按照其他答案的建议使用 Win32 文件更改通知 API (FindFirstChangeNotification)。警告:大约 2000 年 Trend Micro 实时病毒扫描程序会将更改组合在一起,因此在请求文件系统更改列表时需要使用非常大的缓冲区。

如果您没有正在运行的应用程序,您可以打开 ntfs 日志并扫描日志以查找更改http://msdn.microsoft.com/en-us/library/aa363798(VS.85).aspx但这可以是当更改的数量大于文件的数量时,比扫描整个目录要慢。

于 2008-09-11T14:39:32.977 回答
0

从有人提到的双重帖子中:WMI Event Sink

不过仍在寻找更好的答案。

于 2008-09-11T14:51:43.773 回答