[WinAPI] Cum monitorizez un folder?

Folosire Windows API in programe C/C++ (forum moderat)
Post Reply
User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3778
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

[WinAPI] Cum monitorizez un folder?

Post by Ovidiu Cucu » 19 Oct 2007, 19:14

Intrebare
Cum pot sa monitorizez un folder sa vad, de exemplu, cand un fisier a fost adaugat, sters, sau modificat?

Raspuns
O cale usoara este de a utiliza FindFirstChangeNotification, FindNextChangeNotification si una dintre functiile "wait" (exemplu WaitForSingleObject).

Exemplu

Code: Select all

DWORD WINAPI FolderFilesWatchDogThread(LPVOID lpParam) // thread procedure
{
   HANDLE hFileChange = 
      ::FindFirstChangeNotification((LPCTSTR)lpParam, // folder path
                                    FALSE,            // don't look in subfolders
                                    FILE_NOTIFY_CHANGE_FILE_NAME); 
                                                      // watch for
                                                      // renaming, creating, 
                                                      // or deleting a file
   if(INVALID_HANDLE_VALUE == hFileChange)
   {
      DWORD dwError = ::GetLastError();
      // handle error 
      return dwError;
   }
   
   while(TRUE)
   {
      ::WaitForSingleObject(hFileChange, INFINITE);
      // Bark, bark!!! A file was renamed, created or deleted.
      ::FindNextChangeNotification(hFileChange);
   }
   return 0;
}

   // somewhere in the space...
   ::CreateThread(NULL, 0, FolderFilesWatchDogThread, _T("c:\\temp"), 0, NULL);
Un pic mai sofisticat dar obtinand mai multe informatii (cum ar fi numele fisierului) este sa utilizam ReadDirectoryChangesW.

Exemplu

Code: Select all

DWORD WINAPI FolderWatchThread(LPVOID lpParam) // thread procedure
{
   HANDLE hDirectory =
      ::CreateFile((LPCTSTR)lpParam,    // folder path 
                   FILE_LIST_DIRECTORY,
                   FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
                   NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
   
   if(INVALID_HANDLE_VALUE == hDirectory)
   {
      DWORD dwError = ::GetLastError();
      // handle error
      return dwError;
   }

   DWORD dwBytesReturned = 0;
   const DWORD dwBuffLength = 4096;
   BYTE buffer[dwBuffLength];
   WCHAR wchFileName[_MAX_PATH + 1];
   
   while(::ReadDirectoryChangesW(hDirectory, buffer, dwBuffLength, FALSE,
                                 FILE_NOTIFY_CHANGE_FILE_NAME, &dwBytesReturned, 
                                 NULL, NULL))
   {
      DWORD dwNextEntryOffset = 0;
      PFILE_NOTIFY_INFORMATION pfni = NULL;
      do
      {
         pfni = (PFILE_NOTIFY_INFORMATION)(buffer + dwNextEntryOffset);
         
         switch(pfni->Action)
         {
         case FILE_ACTION_ADDED: 
            // The file was added to the directory. 
            break;
         case FILE_ACTION_REMOVED: 
            // The file was removed from the directory. 
            break;
         case FILE_ACTION_RENAMED_OLD_NAME: 
            // The file was renamed and this is the old name. 
            break;
         case FILE_ACTION_RENAMED_NEW_NAME: 
            // The file was renamed and this is the new name.
            break;
            // ...
         }
         memcpy(wchFileName, pfni->FileName, pfni->FileNameLength);
         wchFileName[pfni->FileNameLength / sizeof(WCHAR)] = L'\0';
         // Enjoy of added, removed, or modified file name...
         dwNextEntryOffset += pfni->NextEntryOffset; // next please!
      }while(pfni->NextEntryOffset != 0);
   } 
   ::CloseHandle(hDirectory);
   return 0;
}

<< Back to Windows API Index



Post Reply