如何查看目录的子文件是否已更改

时间:2008-09-11 14:30:19

标签: c++ windows filesystems ntfs

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

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

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

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

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

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

更新:我确实需要一种方法来执行此操作,而不会在更改发生时运行进程。因此,安装文件系统观察程序对我来说不是最佳选择。

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

8 个答案:

答案 0 :(得分:6)

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

HANDLE dwChangeHandles[2]; 
dwChangeHandles[0] = FindFirstChangeNotification( 
      lpDir,                          // directory to watch 
      FALSE,                          // do not watch subtree 
      FILE_NOTIFY_CHANGE_FILE_NAME);  // watch file name changes 

   if (dwChangeHandles[0] == INVALID_HANDLE_VALUE) 
   {
     printf("\n ERROR: FindFirstChangeNotification function failed.\n");
     ExitProcess(GetLastError()); 
   }

// Watch the subtree for directory creation and deletion.  
   dwChangeHandles[1] = FindFirstChangeNotification( 
      lpDrive,                       // directory to watch 
      TRUE,                          // watch the subtree 
      FILE_NOTIFY_CHANGE_DIR_NAME);  // watch dir name changes 

   if (dwChangeHandles[1] == INVALID_HANDLE_VALUE) 
   {
     printf("\n ERROR: FindFirstChangeNotification function failed.\n");
     ExitProcess(GetLastError()); 
   }

然后等待通知:

 while (TRUE) 
   { 
   // Wait for notification. 
      printf("\nWaiting for notification...\n");

      DWORD dwWaitStatus = WaitForMultipleObjects(2, dwChangeHandles, 
         FALSE, INFINITE); 

      switch (dwWaitStatus) 
      { 
         case WAIT_OBJECT_0: 

         // A file was created, renamed, or deleted in the directory.
         // Restart the notification. 
             if ( FindNextChangeNotification(dwChangeHandles[0]) == FALSE )
             {
               printf("\n ERROR: FindNextChangeNotification function failed.\n");
               ExitProcess(GetLastError()); 
             }
             break; 

         case WAIT_OBJECT_0 + 1: 

         // Restart the notification. 
             if (FindNextChangeNotification(dwChangeHandles[1]) == FALSE )
             {
               printf("\n ERROR: FindNextChangeNotification function failed.\n");
               ExitProcess(GetLastError()); 
             }
             break; 

         case WAIT_TIMEOUT:

         // A time-out occurred. This would happen if some value other 
         // than INFINITE is used in the Wait call and no changes occur.
         // In a single-threaded environment, you might not want an
         // INFINITE wait.

            printf("\nNo changes in the time-out period.\n");
            break;

         default: 
            printf("\n ERROR: Unhandled dwWaitStatus.\n");
            ExitProcess(GetLastError());
            break;
      }
   }
}

答案 1 :(得分:3)

这可能有些过分,但MS的IFS kit或OSR的FDDK可能是另一种选择。创建自己的文件系统过滤器驱动程序,只需简单监视文件系统的所有更改。

答案 2 :(得分:2)

ReadDirectoryChangesW

this CodeProject article

中的一些优秀示例代码

答案 3 :(得分:1)

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

您可以使用archive bit加快速度(尽管它可能会破坏您的备份软件,因此请谨慎行事)。

  

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

     

由于归档位是二进制位,因此   是1还是0,或者在这种情况下更多   经常叫set(1)和清除   (0)。操作系统设置   每次文件存档位   创建,移动,重命名或以其他方式   以任何方式修改。存档位   因此代表两个中的一个   州:“改变”和“未改变”   自上次备份以来。

     

存档位不受影响   只是阅读一个文件。当文件是   复制,原始文件的存档   bit不受影响,但副本是   存档位将在当时设置   复制完成。

所以过程将是:

  1. 清除所有文件上的存档位
  2. 让文件系统随时间变化
  3. 扫描所有文件 - 任何设置的存档位已更改
  4. 这将消除您的程序保持状态的必要性,并且因为您只是遍历目录条目(存储位的位置)并且它们是群集的,所以它应该非常非常快。

    但是,如果您可以在更改期间运行流程,那么您将需要查看FileSystemWatcher类。这是example如何使用它。

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

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

    - 亚当

答案 4 :(得分:1)

也许你可以按照here的说明使用NTFS 5 Change Journal和DeviceIoControl

答案 5 :(得分:0)

如果您不反对使用.NET,FileSystemWatcher类将很容易为您处理。

答案 6 :(得分:0)

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

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

答案 7 :(得分:0)

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

仍在寻找更好的答案。