Dela via


Hämta katalogändringsmeddelanden

Ett program kan övervaka innehållet i en katalog och dess underkataloger med hjälp av ändringsmeddelanden. Att vänta på ett ändringsmeddelande motsvarar att ha en läsåtgärd som väntar på en katalog och dess underkataloger, om det behövs. När något ändras i katalogen som övervakas slutförs läsåtgärden. Ett program kan till exempel använda dessa funktioner för att uppdatera en kataloglista när ett filnamn i den övervakade katalogen ändras.

Ett program kan ange en uppsättning villkor som utlöser ett ändringsmeddelande med hjälp av funktionen FindFirstChangeNotification. Villkoren omfattar ändringar av filnamn, katalognamn, attribut, filstorlek, tidpunkt för senaste skrivning och säkerhet. Den här funktionen returnerar också ett handtag som kan väntas på med hjälp av väntefunktioner. Om väntevillkoret är uppfyllt kan FindNextChangeNotification användas för att tillhandahålla en meddelandereferens för att vänta på efterföljande ändringar. Dessa funktioner anger dock inte den faktiska ändring som uppfyllde väntevillkoret.

Använd FindCloseChangeNotification för att stänga meddelandehandtaget.

Om du vill hämta information om den specifika ändringen som en del av meddelandet använder du funktionen ReadDirectoryChangesW. Med den här funktionen kan du också tillhandahålla en kompletteringsrutin.

Obs

Funktionerna FindFirstChangeNotification och ReadDirectoryChangesW är ömsesidigt uteslutande. Du bör använda det ena eller det andra, men inte båda.

Information om hur du spårar ändringar på en volym finns i ändra journaler.

I följande exempel övervakas katalogträdet för ändringar av katalognamn. Den övervakar också en katalog för filnamnsändringar. I exemplet används funktionen FindFirstChangeNotification för att skapa två notifikationshandtag och funktionen WaitForMultipleObjects för att vänta på att handtagen. När en katalog skapas eller tas bort i trädet bör exemplet uppdatera hela katalogträdet. När en fil skapas eller tas bort i katalogen bör exemplet uppdatera katalogen.

Not

Det här förenklade exemplet använder funktionen ExitProcess för avslutning och rensning, men mer komplexa program bör alltid använda korrekt resurshantering, till exempel FindCloseChangeNotification där det är lämpligt.

 

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