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

发布于 2024-07-04 17:02:17 字数 402 浏览 8 评论 0 原文

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

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

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

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

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

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

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

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

In Windows, is there an easy way to tell if a folder has a subfile that has changed?

I verified, and the last modified date on the folder does not get updated when a subfile changes.

Is there a registry entry I can set that will modify this behavior?

If it matters, I am using an NTFS volume.

I would ultimately like to have this ability from a C++ program.

Scanning an entire directory recursively will not work for me because the folder is much too large.

Update: I really need a way to do this without a process running while the change occurs. So installing a file system watcher is not optimal for me.

Update2: The archive bit will also not work because it has the same problem as the last modification date. The file's archive bit will be set, but the folders will not.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

酷到爆炸 2024-07-11 17:02:17

ReadDirectoryChangesW

这篇 CodeProject 文章

ReadDirectoryChangesW

Some excellent sample code in this CodeProject article

霓裳挽歌倾城醉 2024-07-11 17:02:17

这也许有点过分了,但是 MS 的 IFS 套件 或 <来自 OSR 的 href="http://www.osr.com/toolkits_fddk.shtml" rel="nofollow noreferrer">FDDK 可能是一种替代方案。 创建您自己的文件系统过滤器驱动程序,并简单地监视文件系统的所有更改。

This is perhaps overkill, but the IFS kit from MS or the FDDK from OSR might be an alternative. Create your own filesystem filter driver with simple monitoring of all changes to the filesystem.

浅唱ヾ落雨殇 2024-07-11 17:02:17

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

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;
      }
   }
}

This article should help. Basically, you create one or more notification object such as:

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()); 
   }

and then you wait for a notification:

 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;
      }
   }
}
不乱于心 2024-07-11 17:02:17

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

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

Nothing easy - if you have a running app you can use the Win32 file change notification apis (FindFirstChangeNotification) as suggested with the other answers. warning: circa 2000 trend micro real-time virus scanner would group the changes together making it necessary to use really large buffers when requesting the file system change lists.

If you don't have a running app, you can turn on ntfs journaling and scan the journal for changes http://msdn.microsoft.com/en-us/library/aa363798(VS.85).aspx but this can be slower than scanning the whole directory when the # of changes is larger than the # of files.

小红帽 2024-07-11 17:02:17

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

If you are not opposed to using .NET the FileSystemWatcher class will handle this for you fairly easily.

清君侧 2024-07-11 17:02:17

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

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

From the double post someone mentioned: WMI Event Sink

Still looking for a better answer though.

橪书 2024-07-11 17:02:17

也许您可以将 NTFS 5 更改日志与 DeviceIoControl 结合使用,如此处所述

Perhaps you can use the NTFS 5 Change Journal with DeviceIoControl as explained here

请止步禁区 2024-07-11 17:02:17

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

您可以使用存档位来加快速度(尽管它可能会弄乱您的备份软件,所以请小心行事)。

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

由于归档位是二进制位,因此
是 1 或 0,或者在本例中更多
经常被称为set(1)和clear
(0)。 操作系统设置
任何时候文件被归档的位
创建、移动、重命名或以其他方式
以任何方式修改。 存档位
因此代表两个之一
状态:“已更改”和“未更改”
自上次备份以来。

存档位不受
只是读取一个文件。 当一个文件是
已复制,原始文件的存档
位不受影响,但是副本的
此时将设置存档位
副本已制作。

因此,过程将是:

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

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

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

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

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

-亚当

If you can't run a process when the change occurs, then there's not much you can do except scan the filesystem, and check the modification date/time. This requires you to store each file's last date/time, though, and compare.

You can speed this up by using the archive bit (though it may mess up your backup software, so proceed carefully).

An archive bit is a file attribute
present in many computer file systems,
notably FAT, FAT32, and NTFS. The
purpose of an archive bit is to track
incremental changes to files for the
purpose of backup, also called
archiving.

As the archive bit is a binary bit, it
is either 1 or 0, or in this case more
frequently called set (1) and clear
(0). The operating system sets the
archive bit any time a file is
created, moved, renamed, or otherwise
modified in any way. The archive bit
therefore represents one of two
states: "changed" and "not changed"
since the last backup.

Archive bits are not affected by
simply reading a file. When a file is
copied, the original file's archive
bit is unaffected, however the copy's
archive bit will be set at the time
the copy is made.

So the process would be:

  1. Clear the archive bit on all the files
  2. Let the file system change over time
  3. Scan all the files - any with the archive bit set have changed

This will eliminate the need for your program to keep state, and since you're only going over the directory entries (where the bit is stored) and they are clustered, it should be very, very fast.

If you can run a process during the changes, however, then you'll want to look at the FileSystemWatcher class. Here's an example of how you might use it.

It also exists in .NET (for future searchers of this type of problem)

Perhaps you can leave a process running on the machine watching for changes and creating a file for you to read later.

-Adam

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文