Bagikan melalui


Mendapatkan Pemberitahuan Perubahan Direktori

Aplikasi dapat memantau konten direktori dan subdirektorinya dengan menggunakan pemberitahuan perubahan. Menunggu pemberitahuan perubahan mirip dengan operasi baca yang tertunda terhadap direktori dan, jika perlu, subdirektorinya. Ketika sesuatu berubah dalam direktori yang sedang diawasi, operasi baca selesai. Misalnya, aplikasi dapat menggunakan fungsi-fungsi ini untuk memperbarui daftar direktori setiap kali nama file dalam direktori yang dipantau berubah.

Aplikasi dapat menentukan serangkaian kondisi yang memicu pemberitahuan perubahan dengan menggunakan fungsi FindFirstChangeNotification . Kondisi termasuk perubahan pada nama file, nama direktori, atribut, ukuran file, waktu penulisan terakhir, dan keamanan. Fungsi ini juga mengembalikan handel yang dapat ditunggu dengan menggunakan fungsi tunggu. Jika kondisi tunggu terpenuhi, FindNextChangeNotification dapat digunakan untuk memberikan handel pemberitahuan untuk menunggu perubahan berikutnya. Namun, fungsi-fungsi ini tidak menunjukkan perubahan aktual yang memenuhi kondisi tunggu.

Gunakan FindCloseChangeNotification untuk menutup handel pemberitahuan.

Untuk mengambil informasi tentang perubahan tertentu sebagai bagian dari pemberitahuan, gunakan fungsi ReadDirectoryChangesW . Fungsi ini juga memungkinkan Anda untuk memberikan rutinitas penyelesaian.

Untuk melacak perubahan pada volume, lihat mengubah jurnal.

Contoh berikut memantau pohon direktori untuk perubahan nama direktori. Ini juga memantau direktori untuk perubahan nama file. Contohnya menggunakan fungsi FindFirstChangeNotification untuk membuat dua handel pemberitahuan dan fungsi WaitForMultipleObjects untuk menunggu di handel. Setiap kali direktori dibuat atau dihapus di pohon, contohnya harus memperbarui seluruh pohon direktori. Setiap kali file dibuat atau dihapus di direktori, contohnya harus merefresh direktori.

Catatan

Contoh sederhana ini menggunakan fungsi ExitProcess untuk penghentian dan pembersihan, tetapi aplikasi yang lebih kompleks harus selalu menggunakan manajemen sumber daya yang tepat seperti FindCloseChangeNotification jika sesuai.

 

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