应用程序可以使用更改通知来监视目录及其子目录的内容。 等待更改通知类似于对目录以及必要时对其子目录挂起读取操作。 监视的目录中的内容发生更改时,读取操作将完成。 例如,每当被监视目录内的文件名发生更改时,应用程序都可以使用这些函数更新目录列表。
应用程序可以使用 FindFirstChangeNotification 函数指定触发更改通知的一组条件。 条件包括对文件名、目录名称、属性、文件大小、上次写入时间和安全性的更改。 此函数还会返回可以使用 wait 函数等待的句柄。 如果满足了等待条件,则 FindNextChangeNotification 可用于提供通知句柄来等待后续更改。 但是,这些函数并不指示满足等待条件的实际更改。
使用 FindCloseChangeNotification 关闭通知句柄。
若要在通知中检索有关特定更改的信息,请使用 ReadDirectoryChangesW 函数。 此函数还允许你提供完成例程。
注意
FindFirstChangeNotification 和 ReadDirectoryChangesW 函数互斥。 你应该使用一种方法或另一种方法,但不能二者都用。
若要跟踪卷上的更改,请参阅更改日记帐。
以下示例监视目录树中的目录名称更改。 它还监视目录中的文件名更改。 该示例使用 FindFirstChangeNotification 函数来创建两个通知句柄,使用 WaitForMultipleObjects 函数来等待这些句柄。 每当在树中创建或删除目录时,该示例都应更新整个目录树。 每当在目录中创建或删除文件时,该示例都应刷新目录。
注意
此简单示例使用 ExitProcess 函数进行终止和清理,但更复杂的应用程序始终应酌情使用适当的资源管理,例如 FindCloseChangeNotification。
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <tchar.h>
void RefreshDirectory(LPTSTR);
void RefreshTree(LPTSTR);
void WatchDirectory(LPTSTR);
void _tmain(int argc, TCHAR *argv[])
{
    if(argc != 2)
    {
        _tprintf(TEXT("Usage: %s <dir>\n"), argv[0]);
        return;
    }
    WatchDirectory(argv[1]);
}
void WatchDirectory(LPTSTR lpDir)
{
   DWORD dwWaitStatus; 
   HANDLE dwChangeHandles[2]; 
   TCHAR lpDrive[4];
   TCHAR lpFile[_MAX_FNAME];
   TCHAR lpExt[_MAX_EXT];
   _tsplitpath_s(lpDir, lpDrive, 4, NULL, 0, lpFile, _MAX_FNAME, lpExt, _MAX_EXT);
   lpDrive[2] = (TCHAR)'\\';
   lpDrive[3] = (TCHAR)'\0';
 
// Watch the directory for file creation and deletion. 
 
   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()); 
   }
 
// Make a final validation check on our handles.
   if ((dwChangeHandles[0] == NULL) || (dwChangeHandles[1] == NULL))
   {
     printf("\n ERROR: Unexpected NULL from FindFirstChangeNotification.\n");
     ExitProcess(GetLastError()); 
   }
// Change notification is set. Now wait on both notification 
// handles and refresh accordingly. 
 
   while (TRUE) 
   { 
   // Wait for notification.
 
      printf("\nWaiting for notification...\n");
      dwWaitStatus = WaitForMultipleObjects(2, dwChangeHandles, 
         FALSE, INFINITE); 
 
      switch (dwWaitStatus) 
      { 
         case WAIT_OBJECT_0: 
 
         // A file was created, renamed, or deleted in the directory.
         // Refresh this directory and restart the notification.
 
             RefreshDirectory(lpDir); 
             if ( FindNextChangeNotification(dwChangeHandles[0]) == FALSE )
             {
               printf("\n ERROR: FindNextChangeNotification function failed.\n");
               ExitProcess(GetLastError()); 
             }
             break; 
 
         case WAIT_OBJECT_0 + 1: 
 
         // A directory was created, renamed, or deleted.
         // Refresh the tree and restart the notification.
 
             RefreshTree(lpDrive); 
             if (FindNextChangeNotification(dwChangeHandles[1]) == FALSE )
             {
               printf("\n ERROR: FindNextChangeNotification function failed.\n");
               ExitProcess(GetLastError()); 
             }
             break; 
 
         case WAIT_TIMEOUT:
         // A timeout 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 timeout period.\n");
            break;
         default: 
            printf("\n ERROR: Unhandled dwWaitStatus.\n");
            ExitProcess(GetLastError());
            break;
      }
   }
}
void RefreshDirectory(LPTSTR lpDir)
{
   // This is where you might place code to refresh your
   // directory listing, but not the subtree because it
   // would not be necessary.
   _tprintf(TEXT("Directory (%s) changed.\n"), lpDir);
}
void RefreshTree(LPTSTR lpDrive)
{
   // This is where you might place code to refresh your
   // directory listing, including the subtree.
   _tprintf(TEXT("Directory tree (%s) changed.\n"), lpDrive);
}