2013-04-15 29 views
0
void TestDirChanges(LPCWSTR path) 
{ 
/* 
FileName member of FILE_NOTIFY_INFORMATION has only one WCHAR according to definition. Most likely, this field will have more characters. 
So the expected size of one item is (sizeof(FILE_NOTIFY_INFORMATION) + MAX_PATH * sizeof(WCHAR)). 
Prepare buffer for 256 items. 
*/ 
char buf[256 * (sizeof(FILE_NOTIFY_INFORMATION) + MAX_PATH * sizeof(WCHAR))] = {0}; 
DWORD bytesReturned = 0; 
BOOL result = FALSE; 
FILE_NOTIFY_INFORMATION *fni = NULL; 

HANDLE hDir = CreateFile(path, 
    FILE_LIST_DIRECTORY | STANDARD_RIGHTS_READ, 
    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 
    NULL, 
    OPEN_EXISTING, 
    FILE_FLAG_BACKUP_SEMANTICS, 
    NULL); 

if (!hDir || hDir == INVALID_HANDLE_VALUE) 
{ 
    wprintf(L"CreateFile failed\n"); 
    return; 
} 

while (1) 
{ 
    result = ReadDirectoryChangesW(hDir, 
     buf, 
     sizeof(buf)/sizeof(*buf), 
     TRUE, /* monitor the entire subtree */ 
     FILE_NOTIFY_CHANGE_FILE_NAME | 
      FILE_NOTIFY_CHANGE_DIR_NAME | 
      FILE_NOTIFY_CHANGE_ATTRIBUTES | 
      FILE_NOTIFY_CHANGE_SIZE | 
      FILE_NOTIFY_CHANGE_LAST_WRITE | 
      FILE_NOTIFY_CHANGE_LAST_ACCESS | 
      FILE_NOTIFY_CHANGE_CREATION | 
      FILE_NOTIFY_CHANGE_SECURITY, 
     &bytesReturned, 
     NULL, 
     NULL); 

    if (result && bytesReturned) 
    { 
     wchar_t filename[MAX_PATH]; 
     wchar_t action[256]; 
     for (fni = (FILE_NOTIFY_INFORMATION*)buf; fni;) 
     { 
      switch (fni->Action) 
      { 
      case FILE_ACTION_ADDED: 
       wcscpy_s(action, sizeof(action)/sizeof(*action), L"File added:"); 
       break; 

      case FILE_ACTION_REMOVED: 
       wcscpy_s(action, sizeof(action)/sizeof(*action), L"File removed:"); 
       break; 

      case FILE_ACTION_MODIFIED: 
       wcscpy_s(action, sizeof(action)/sizeof(*action), L"File modified:"); 
       break; 

      case FILE_ACTION_RENAMED_OLD_NAME: 
       wcscpy_s(action, sizeof(action)/sizeof(*action), L"File renamed, was:"); 
       break; 

      case FILE_ACTION_RENAMED_NEW_NAME: 
       wcscpy_s(action, sizeof(action)/sizeof(*action), L"File renamed, now is:"); 
       break; 

      default: 
       swprintf_s(action, sizeof(action)/sizeof(*action), L"Unkonwn action: %ld. File name is:", fni->Action); 
      } 

      if (fni->FileNameLength) 
      { 
       wcsncpy_s(filename, MAX_PATH, fni->FileName, fni->FileNameLength/2); 
       filename[fni->FileNameLength/2] = 0; 
       wprintf(L"%s '%s'\n", action, filename); 
      } 
      else 
      { 
       wprintf(L"%s <EMPTY>\n", action); 
      }     

      if (fni->NextEntryOffset) 
      { 
       char *p = (char*)fni; 
       fni = (FILE_NOTIFY_INFORMATION*)(p + fni->NextEntryOffset); 
      } 
      else 
      { 
       fni = NULL; 
      } 
     } 
    } 
    else 
    { 
     wprintf(L"ReadDirectoryChangesW failed\n"); 
    } 
} 

CloseHandle(hDir); 
} 

我的代碼運行在Win32控制檯很好,但是當我在WIN32項目中使用它,ReadDirectoryChangesW不起作用。它運行並且我的編程停止工作。 請幫助我, 謝謝,ReadDirectoryChangesW在WIN32 API項目中出錯?

+1

什麼是錯誤? – Rohan

+0

當我在WIN32 API Project而不是控制檯上運行它時,我的程序停止工作。我無法關閉它。 –

+2

你如何期望「關掉它」?你有一個無盡的循環(很可能不在一個單獨的線程)。 –

回答

1

看起來像你阻止在win32項目的UI線程和應用程序似乎凍結,它不會迴應。啓動一個工作者線程並在工作線程中執行這些工作。

我認爲這是更好地使用通知API的喜歡SHChangeNotifyRegister,將讓你知道,如果到目錄的任何變化已經發生,然後你可以閱讀,而不是在while循環做它的目錄。也是應用程序unicode?您正在使用ReadDirectoryChangesW

http://msdn.microsoft.com/en-us/library/windows/desktop/bb762120.aspx

+0

我正在嘗試使用ReadDirectoryChangesW。你能不能給我一個例子關於SHChangeNotifyRegister –

+0

您可以閱讀SHChangeNotifyRegister'的'在MSDN文檔。這將有助於您在通知有變化的情況下通知您,從而擺脫while循環。一旦你得到通知,你必須要做同樣的事情來讀取已經改變的目錄。 http://msdn.microsoft.com/en-us/library/windows/desktop/bb762120(v=vs.85).aspx進行SDK示例 –

+0

它們具有參考文檔我使用WIN32 API C/C++。它有效嗎? –