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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/56682/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 11:10:27  来源:igfitidea点击:

How to see if a subfile of a directory has changed

c++windowsfilesystemsntfs

提问by Brian R. Bondy

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

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

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.

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

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

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

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.

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

采纳答案by botismarius

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

回答by Jonas Gulle

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

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

回答by Serge Wautier

回答by PabloG

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

也许你可以使用NTFS 5更改日志与作为DeviceIoControl的解释这里

回答by Adam Davis

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.

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

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

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

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

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 FileSystemWatcherclass. Here's an exampleof how you might use it.

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

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

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

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

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

-Adam

-亚当

回答by NotMyself

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

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

回答by Tony Lee

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.

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

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).aspxbut this can be slower than scanning the whole directory when the # of changes is larger than the # of files.

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

回答by Brian R. Bondy

From the double post someone mentioned: WMI Event Sink

来自有人提到的双重帖子:WMI Event Sink

Still looking for a better answer though.

尽管如此,仍在寻找更好的答案。