• VC++ 监控指定目录改变


    转载:http://www.cnblogs.com/doublesnke/archive/2011/08/16/2141374.html

    VC++实施文件监控:实例和详解

    相关帮助: http://hi.baidu.com/jiahaosoft/blog/item/b441d1218eebece0d6cae274.html

    我这里只介绍采用ReadDirectoryChangesW对文件目录实施监控

    关键代码

    CfgdsgDlg * dlg = (CfgdsgDlg*)lparam;
     
        HANDLE hDir;
        char notify[1024];
        DWORD cbBytes,i;
        char AnsiChar[3];
        wchar_t UnicodeChar[2];
        CString path;
     
        FILE_NOTIFY_INFORMATION *pnotify=(FILE_NOTIFY_INFORMATION *)notify;
        FILE_NOTIFY_INFORMATION *tmp;
     
        GetCurrentDirectory(MAX_PATH,path.GetBuffer(MAX_PATH+1));
        hDir = CreateFile( path, FILE_LIST_DIRECTORY,
            FILE_SHARE_READ |
            FILE_SHARE_WRITE |
            FILE_SHARE_DELETE, NULL,
            OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS |
            FILE_FLAG_OVERLAPPED, NULL);
        if (hDir == INVALID_HANDLE_VALUE)
        {
     
            dlg->m_edit.ReplaceSel("hDir:INVALID_HANDLE_VALUE ");
            return 0;
        }
     
        while (TRUE)
        {
            if(ReadDirectoryChangesW(hDir, &notify, sizeof(notify),
                FALSE, FILE_NOTIFY_CHANGE_FILE_NAME| FILE_NOTIFY_CHANGE_LAST_WRITE,
                &cbBytes, NULL, NULL))
            {
     
                tmp = pnotify;
     
                switch(tmp->Action)
                {
                case FILE_ACTION_ADDED:
     
                    dlg->m_edit.ReplaceSel("Directory/File added (添加文件)- ");
                    break;
                case FILE_ACTION_REMOVED:
                    dlg->m_edit.ReplaceSel("Directory/File removed (删除文件)- ");
                    break;
                case FILE_ACTION_MODIFIED:
                    dlg->m_edit.ReplaceSel("Directory/File modified (修改文件内容)- ");
                    break;
                case FILE_ACTION_RENAMED_OLD_NAME:
                    dlg->m_edit.ReplaceSel("Directory/File old name (修改文件名字)- ");
                    break;
                case FILE_ACTION_RENAMED_NEW_NAME:
                    dlg->m_edit.ReplaceSel("Directory/File new name - ");
                    break;
                default:
                    break;
                }
            }
        }

      

    FILE_NOTIFY_INFORMATION //可以确定是那个文件进行的修改

    typedef struct _FILE_NOTIFY_INFORMATION {
      DWORD NextEntryOffset;
      DWORD Action;//动作
      DWORD FileNameLength;//文件名字的长度
      WCHAR FileName[1];//文件名字
    } FILE_NOTIFY_INFORMATION, 
    *PFILE_NOTIFY_INFORMATION;

    ReadDirectoryChangesW 返回类型(见MSDN)

    ValueMeaning

    FILE_ACTION_ADDED
    0x00000001

    The file was added to the directory.

    FILE_ACTION_REMOVED
    0x00000002

    The file was removed from the directory.

    FILE_ACTION_MODIFIED
    0x00000003

    The file was modified. This can be a change in the time stamp or attributes.

    FILE_ACTION_RENAMED_OLD_NAME
    0x00000004

    The file was renamed and this is the old name.

    FILE_ACTION_RENAMED_NEW_NAME
    0x00000005

    The file was renamed and this is the new name.

    效果如下:

    不足的地方:

    只能检测到指定目录和下一级目录,超过目录级数,该函数检测不到。

    2. 转载:http://blog.csdn.net/visualeleven/article/details/7562014

     1 // .h文件
     2 #pragma once
     3 
     4 typedef void (*PFN_NotifyAction)(DWORD dwAction, LPWSTR szFile, DWORD dwLength);
     5 
     6 class CDirectoryWatch
     7 {
     8 public:
     9     CDirectoryWatch(void);
    10     virtual ~CDirectoryWatch(void);
    11 
    12 public:
    13     BOOL StartDirectoryWatch(LPCTSTR lpszDirectory, PFN_NotifyAction pFn_NotifyAction);
    14     BOOL StopDirectoryWatch(void);
    15 
    16 private:
    17     static UINT __cdecl ThreadProc(LPVOID lParam);
    18     static UINT __cdecl DirectoryWatch(LPVOID lParam);
    19 
    20 private:
    21     HANDLE m_hFile;
    22     CWinThread* m_pThread;
    23     TCHAR m_szDirectory[MAX_PATH];
    24 };
      1 // .cpp文件
      2 #include "StdAfx.h"
      3 #include "DirectoryWatch.h"
      4 #include <strsafe.h>
      5 
      6 typedef enum
      7 {
      8     MSG_STARTWATCH = (WM_USER + 0x11),
      9     MSG_STOPWATCH,
     10     MSG_EXITTHREAD
     11 };
     12 
     13 #define MAX_BUFFER_SIZE    (1024)
     14 
     15 typedef struct _tagWATCHPARAMETERS
     16 {
     17     _tagWATCHPARAMETERS()
     18     {
     19         hFile = INVALID_HANDLE_VALUE;
     20         hEvent = NULL;
     21         memset(&ol, 0, sizeof(OVERLAPPED));
     22         pBuffer = NULL;
     23         dwBufferSize = 0;
     24         bExit = FALSE;
     25         pFn_NotifyAction = NULL;
     26     }
     27     HANDLE hFile;
     28     HANDLE hEvent;
     29     OVERLAPPED ol;
     30     BYTE* pBuffer;
     31     DWORD dwBufferSize;
     32     BOOL bExit;
     33     PFN_NotifyAction pFn_NotifyAction;
     34 }WATCH_PARAMETERS, *PWATCH_PARAMETERS;
     35 
     36 CDirectoryWatch::CDirectoryWatch() : m_hFile(INVALID_HANDLE_VALUE), m_pThread(NULL)
     37 {
     38     memset(m_szDirectory, 0, sizeof(m_szDirectory));
     39 
     40     m_pThread = AfxBeginThread(ThreadProc, NULL, 0, CREATE_SUSPENDED, 0, NULL);
     41     if(NULL == m_pThread)
     42     {
     43         TRACE("Error Code : %d
    ", GetLastError());
     44         return ;
     45     }
     46     m_pThread->m_bAutoDelete = FALSE;
     47     m_pThread->ResumeThread();
     48 }
     49 
     50 
     51 CDirectoryWatch::~CDirectoryWatch()
     52 {
     53     if(INVALID_HANDLE_VALUE != m_hFile)
     54     {
     55         CloseHandle(m_hFile);
     56         m_hFile = INVALID_HANDLE_VALUE;
     57     }
     58 
     59     if((NULL != m_pThread) && (NULL != m_pThread->m_hThread))
     60     {
     61 
     62         m_pThread->PostThreadMessage(MSG_EXITTHREAD, 0, 0);
     63         WaitForSingleObject(m_pThread->m_hThread, INFINITE);
     64         delete m_pThread;
     65         m_pThread = NULL;
     66     }
     67 }
     68 
     69 BOOL CDirectoryWatch::StartDirectoryWatch(LPCTSTR lpszDirectory, PFN_NotifyAction pFn_NotifyAction)
     70 {
     71     if(NULL == m_pThread)
     72     {
     73         return FALSE;
     74     }
     75 
     76     if(NULL == lpszDirectory)
     77     {
     78         return FALSE;
     79     }
     80 
     81     if(NULL == pFn_NotifyAction)
     82     {
     83         return FALSE;
     84     }
     85 
     86     if(!PathFileExists(lpszDirectory))
     87     {
     88         TRACE("Error Code : %d
    ", GetLastError());
     89         return FALSE;
     90     }
     91 
     92     if(!PathIsDirectory(lpszDirectory))
     93     {
     94         TRACE("Error Code : %d
    ", GetLastError());
     95         return FALSE;
     96     }
     97 
     98     if(0 == _tcslen(m_szDirectory))
     99     {
    100         StringCchPrintf(m_szDirectory, _countof(m_szDirectory), _T("%s"), lpszDirectory);
    101     }
    102     else if(CSTR_EQUAL != CompareStringOrdinal(m_szDirectory, -1, lpszDirectory, -1, TRUE))
    103     {
    104         TRACE("Not Change Directory.
    ");
    105         return FALSE;
    106     }
    107 
    108     if(INVALID_HANDLE_VALUE == m_hFile)
    109     {
    110         m_hFile = CreateFile(lpszDirectory, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
    111             NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL);
    112         if(INVALID_HANDLE_VALUE == m_hFile)
    113         {
    114             TRACE("Error Code : %d
    ", GetLastError());
    115             return FALSE;
    116         }
    117     }
    118 
    119     return m_pThread->PostThreadMessage(MSG_STARTWATCH, (WPARAM)m_hFile, (LPARAM)pFn_NotifyAction);
    120 }
    121 
    122 BOOL CDirectoryWatch::StopDirectoryWatch()
    123 {
    124     if(NULL != m_pThread)
    125     {
    126         return m_pThread->PostThreadMessage(MSG_STOPWATCH, 0, 0);
    127     }
    128 
    129     return FALSE;
    130 }
    131 
    132 UINT __cdecl CDirectoryWatch::DirectoryWatch(LPVOID lParam)
    133 {
    134     WATCH_PARAMETERS* pParam = (WATCH_PARAMETERS*)lParam;
    135     if(NULL == pParam)
    136     {
    137         return 0;
    138     }
    139     HANDLE& hFile = pParam->hFile;
    140     BYTE* pBuffer = pParam->pBuffer;
    141     DWORD dwBufferSize = pParam->dwBufferSize;
    142     OVERLAPPED& ol = pParam->ol;
    143     HANDLE& hEvent = pParam->hEvent;
    144     BOOL& bExit = pParam->bExit;
    145     PFN_NotifyAction pFn_NotifyAction = pParam->pFn_NotifyAction;
    146     DWORD dwBytesReturn = 0;
    147     DWORD dwRet = WAIT_FAILED;
    148     DWORD dwOffSet = 0;
    149     TCHAR szFile[MAX_PATH] = {0};
    150     while(TRUE)
    151     {
    152         if(WAIT_OBJECT_0 != WaitForSingleObject(hEvent, INFINITE))
    153         {
    154             TRACE("Error Code : %d
    ", GetLastError());
    155             break;
    156         }
    157 
    158         if(bExit)
    159         {
    160             break;
    161         }
    162     
    163         if(!ReadDirectoryChangesW(hFile, pBuffer, dwBufferSize, TRUE, 
    164             FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES
    165             | FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_LAST_ACCESS
    166             | FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_SECURITY, &dwBytesReturn, &ol, NULL))
    167         {
    168             TRACE("Error Code : %d
    ", GetLastError());
    169             break;
    170         }
    171         if(!GetOverlappedResult(hFile, &ol, &dwBytesReturn, TRUE))
    172         {
    173             TRACE("Error Code : %d
    ", GetLastError());
    174             break;
    175         }
    176         FILE_NOTIFY_INFORMATION* pFileNotify = (FILE_NOTIFY_INFORMATION*)pBuffer;
    177         
    178         do 
    179         {
    180             if(pFn_NotifyAction && (WAIT_OBJECT_0 == WaitForSingleObject(hEvent, 0)))
    181             {
    182                 pFn_NotifyAction(pFileNotify->Action, pFileNotify->FileName, (pFileNotify->FileNameLength) / sizeof(WCHAR));
    183             }
    184 
    185             dwOffSet = pFileNotify->NextEntryOffset;
    186             pFileNotify = (FILE_NOTIFY_INFORMATION*)((BYTE*)pFileNotify + dwOffSet);
    187         } while (dwOffSet);
    188     }
    189     TRACE0("DirectoryWatch Thread Exit ... 
    ");
    190     return 0;
    191 }
    192 
    193 UINT __cdecl CDirectoryWatch::ThreadProc(LPVOID lParam)
    194 {
    195     WATCH_PARAMETERS* pParam = new WATCH_PARAMETERS;
    196 
    197     if(NULL == pParam)
    198     {
    199         goto __CLEANUP__;
    200     }
    201 
    202     BYTE* pBuffer = new BYTE[MAX_BUFFER_SIZE];
    203     if(NULL == pBuffer)
    204     {
    205         goto __CLEANUP__;
    206     }
    207     memset(pBuffer, 0, MAX_BUFFER_SIZE);
    208     pParam->pBuffer = pBuffer;
    209     pParam->dwBufferSize = MAX_BUFFER_SIZE;
    210     HANDLE hWatchEvent  = CreateEvent(NULL, TRUE, FALSE, NULL);
    211     if(NULL == hWatchEvent)
    212     {
    213         goto __CLEANUP__;
    214     }
    215     pParam->ol.hEvent = hWatchEvent;
    216     CWinThread* pThread = NULL;
    217     HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    218     if(NULL == hEvent)
    219     {
    220         goto __CLEANUP__;
    221     }
    222     pParam->hEvent = hEvent;
    223     MSG msg;
    224     while(GetMessage(&msg, NULL, 0, 0))
    225     {
    226         switch(msg.message)
    227         {
    228         case MSG_STARTWATCH:
    229             {
    230                 HANDLE hFile = (HANDLE)(msg.wParam);
    231                 PFN_NotifyAction pFn_NotifyAction = (PFN_NotifyAction)(msg.lParam);
    232                 if((INVALID_HANDLE_VALUE == hFile) && (NULL == pFn_NotifyAction))
    233                 {
    234                     break;
    235                 }
    236                 if(NULL == pThread)
    237                 {
    238                     pParam->hFile = hFile;
    239                     pParam->pFn_NotifyAction = pFn_NotifyAction;
    240                     pThread = AfxBeginThread(DirectoryWatch, (LPVOID)pParam, 0, CREATE_SUSPENDED, NULL);
    241                     if(NULL == pThread)
    242                     {
    243                         goto __CLEANUP__;
    244                     }
    245                     pThread->m_bAutoDelete = FALSE;
    246                     pThread->ResumeThread();
    247                 }                
    248                 SetEvent(hEvent);
    249             }
    250             break;
    251 
    252         case MSG_STOPWATCH:
    253             {
    254                 ResetEvent(hEvent);
    255             }
    256             break;
    257 
    258         case MSG_EXITTHREAD:
    259             {
    260                 SetEvent(hEvent);
    261                 pParam->bExit = FALSE;
    262                 
    263                 if((NULL != pThread) && (NULL != pThread->m_hThread))
    264                 {
    265                     WaitForSingleObject(pThread->m_hThread, INFINITE);
    266                     delete pThread;
    267                     pThread = NULL;
    268                 }
    269                 goto __CLEANUP__;
    270             }
    271             
    272         default:
    273             break;
    274         }
    275         TranslateMessage(&msg);
    276         DispatchMessage(&msg);
    277     }
    278 
    279 __CLEANUP__:
    280     if(NULL != hWatchEvent)
    281     {
    282         CloseHandle(hWatchEvent);
    283         hWatchEvent = NULL;
    284     }
    285     if(NULL != pBuffer)
    286     {
    287         delete[] pBuffer;
    288         pBuffer = NULL;
    289     }
    290     if(NULL != pParam)
    291     {
    292         delete pParam;
    293         pParam = NULL;
    294     }
    295     TRACE0("ThreadProc Thread Exit ...
    ");
    296     return 0;
    297 }
     1 // 测试代码
     2 
     3 #include "stdafx.h"
     4 
     5 #include "DirectoryWatch.h"
     6 
     7 void NotifyAction(DWORD dwAction, LPWSTR szFile, DWORD dwLength)
     8 {
     9     switch(dwAction)
    10     {
    11     case FILE_ACTION_ADDED:
    12         wprintf(L"FILE_ACTION_ADDED: 
    	");
    13         break;
    14 
    15     case FILE_ACTION_REMOVED:
    16         wprintf(L"FILE_ACTION_REMOVED: 
    	");
    17         break;
    18 
    19     case FILE_ACTION_MODIFIED:
    20         wprintf(L"FILE_ACTION_MODIFIED: 
    	");
    21         break;
    22 
    23     case FILE_ACTION_RENAMED_OLD_NAME:
    24         wprintf(L"FILE_ACTION_RENAMED_OLD_NAME: 
    	");
    25         break;
    26 
    27     case FILE_ACTION_RENAMED_NEW_NAME:
    28         wprintf(L"FILE_ACTION_RENAMED_NEW_NAME: 
    	");
    29         break;
    30 
    31     default:
    32         break;
    33     }
    34     WCHAR szPath[MAX_PATH] = {0};
    35     wmemcpy(szPath, szFile, min(dwLength, MAX_PATH));
    36     wprintf(L"%s
    ", szPath);
    37 }
    38 
    39 int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
    40 {
    41     CDirectoryWatch watch;
    42     wprintf(L"Start Directory Watch ...
    ");
    43     watch.StartDirectoryWatch(_T("F:\11"), NotifyAction);
    44     Sleep(30 * 1000);    
    45     watch.StopDirectoryWatch();
    46     wprintf(L"Stop Directory Watch ...
    ");
    47 
    48     Sleep(10 * 1000);
    49 
    50     wprintf(L"Start Directory Watch ...
    ");
    51     watch.StartDirectoryWatch(_T("F:\11"), NotifyAction);
    52     Sleep(30 * 1000);    
    53     watch.StopDirectoryWatch();
    54     wprintf(L"Stop Directory Watch ...
    ");
    55     Sleep(30 * 1000);
    56     wprintf(L"Process Exit ...
    ");
    57     return 0;
    58 }

    效果如下图所示:

    [C++]使用ReadDirectoryChangesW API監控檔案系統的改變

    [C++]使用ReadDirectoryChangesW API監控檔案系統的改變

    在C++中若想要監控檔案系統改變有很多方法,可以用FindFirstChangeNotification取得檔案變更、或是Hook底層的API等方法來實現,這邊使用ReadDirectoryChangesW API來實現,該API使用前必須先加入Kernel32.lib。

    image

    並加入Windows.h的標頭檔

    1 #include "Windows.h"
    
    

    這些步驟做完後在程式中就可以看到ReadDirectoryChangesW API了,其函式原型如下:

     1 BOOL WINAPI ReadDirectoryChangesW(
     2   __in         HANDLE hDirectory,
     3   __out        LPVOID lpBuffer,
     4   __in         DWORD nBufferLength,
     5   __in         BOOL bWatchSubtree,
     6   __in         DWORD dwNotifyFilter,
     7   __out_opt    LPDWORD lpBytesReturned,
     8   __inout_opt  LPOVERLAPPED lpOverlapped,
     9   __in_opt     LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
    10 );
    
    

    該API必須帶入八個參數,hDirectory帶入的是要監控的目錄Handle、lpBuffer帶入的是用來回傳變動資料的空間、nBufferLength是lpBuffer空間的大小、bWatchSubtree是指定是否偵測子目錄、dwNotifyFilter是指定監控的目錄有哪些動作時需要通知、lpBytesReturned是用來回傳變動資料內含的長度、lpOverlapped可用來在非同步環境下使用重疊IO用、lpCompletionRoutine則是當監控完成或取消時所呼叫的回調函式。

    其中dwNotifyFilter的值可設定的有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,詳細所代表的意義可參閱ReadDirectoryChangesW function

    了解了函式原型後,就可以開始進入實際的使用。剛有提到說在ReadDirectoryChangesW API函式必須要帶入的第一個參數是要監控的目錄Handle,所以我們必須透過CreateFile API取得要監控的目錄Handle,像是下面這樣:

     1 HANDLE  hDirectoryHandle    = NULL;
     2 
     3 
     4 hDirectoryHandle = ::CreateFileA(
     5     file,                    
     6     FILE_LIST_DIRECTORY,                
     7     FILE_SHARE_READ                        
     8     | FILE_SHARE_WRITE
     9     | FILE_SHARE_DELETE,
    10     NULL,                               
    11     OPEN_EXISTING,                      
    12     FILE_FLAG_BACKUP_SEMANTICS            
    13     | FILE_FLAG_OVERLAPPED,
    14     NULL);  
    15 
    16 if(hDirectoryHandle == INVALID_HANDLE_VALUE)
    17     return;
    
    

    取得監控的目錄Handle後,將其帶入ReadDirectoryChangesw API,順帶帶入像是回傳變動資料的Buffer空間、與要監控的變動類型等必要參數。像是下面這樣:

     1 int        nBufferSize            = 1024;
     2 char*    buffer                = new char[nBufferSize];
     3 DWORD dwBytes = 0;
     4 
     5 memset(buffer, 0, nBufferSize);
     6 
     7 if(!::ReadDirectoryChangesW(
     8     hDirectoryHandle,                        
     9     buffer,                                
    10     nBufferSize,        
    11     bIncludeSubdirectories,             
    12     FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_FILE_NAME,     
    13     &dwBytes,                         
    14     NULL,                    
    15     NULL) || GetLastError() == ERROR_INVALID_HANDLE)
    16 {
    17     break;
    18 }
    19 
    20 if(!dwBytes)
    21 {
    22     printf("Buffer overflow~~
    ");
    23 }
    
    

    這邊需注意到的是,若是變動的資料太多,提供的存儲空間不足以存放時,回傳的變動資料長度會是0,此時所有變動資料都會丟失。這樣的情況多半只會出在一瞬間大量的變動,可以增大存儲空間或是減少監控的變動類型,以減少回傳的資料量,避免溢位的發生。

    若是運行沒發生問題,變動的資料會存放在當初塞進去的存儲空間,該空間的資料其實是FILE_NOTIFY_INFORMATION structure的型態存在,因此我們可將存儲空間的資料轉換成PFILE_NOTIFY_INFORMATION。裡面的Action是我們所關注的變動類型,FileName是變動的檔案名稱,檔案名稱的部分是沒有結尾符號的,必須要搭配FileNameLength去截取。另外變動的資料有時候不止一筆,因此我們必須在這邊用迴圈搭配NextEntryOffset去重覆運行處理流程,處理所有變動的資料。

     1 PFILE_NOTIFY_INFORMATION record = (PFILE_NOTIFY_INFORMATION)buffer;
     2 DWORD cbOffset = 0;
     3 
     4 do
     5 {    
     6     switch (record->Action)
     7     {
     8     case FILE_ACTION_ADDED:    
     9         printf("FILE_ACTION_ADDED:");
    10         break;
    11     case FILE_ACTION_REMOVED:
    12         printf("FILE_ACTION_REMOVED:");
    13         break;
    14     case FILE_ACTION_MODIFIED:
    15         printf("FILE_ACTION_MODIFIED:");
    16         break;
    17     case FILE_ACTION_RENAMED_OLD_NAME:
    18         printf("FILE_ACTION_RENAMED_OLD_NAME:");                
    19         break;
    20 
    21     case FILE_ACTION_RENAMED_NEW_NAME:
    22         printf("FILE_ACTION_RENAMED_NEW_NAME:");
    23         break;
    24 
    25     default:
    26         break;
    27     }        
    28 
    29     char fileBuffer[512];
    30 
    31     WideCharToMultiByte(CP_ACP, 0, record->FileName, record->FileNameLength, fileBuffer, record->FileNameLength, NULL, NULL);  
    32     printf(fileBuffer);
    33     printf("
    ");
    34 
    35     cbOffset = record->NextEntryOffset;
    36     record = (PFILE_NOTIFY_INFORMATION)((LPBYTE) record + cbOffset);
    37 }while(cbOffset);    
     

    這邊示範一個簡易的使用範例,實際使用時最好還是搭配執行緒處理:

      1 // ConsoleApplication10.cpp : Defines the entry point for the console application.
      2 //
      3 
      4 #include "stdafx.h"
      5 #include "Windows.h"
      6 
      7 void MonitorDir(char* file, bool bIncludeSubdirectories = false)
      8 {
      9     int        nBufferSize            = 1024;
     10     char*    buffer                = new char[nBufferSize];    
     11     HANDLE  hDirectoryHandle    = NULL;
     12 
     13 
     14     hDirectoryHandle = ::CreateFileA(
     15         file,                    
     16         FILE_LIST_DIRECTORY,                
     17         FILE_SHARE_READ                        
     18         | FILE_SHARE_WRITE
     19         | FILE_SHARE_DELETE,
     20         NULL,                               
     21         OPEN_EXISTING,                      
     22         FILE_FLAG_BACKUP_SEMANTICS            
     23         | FILE_FLAG_OVERLAPPED,
     24         NULL);  
     25 
     26     if(hDirectoryHandle == INVALID_HANDLE_VALUE)
     27         return;
     28 
     29     while(1)
     30     {
     31         DWORD dwBytes = 0;
     32 
     33         memset(buffer, 0, nBufferSize);
     34 
     35         if(!::ReadDirectoryChangesW(
     36             hDirectoryHandle,                        
     37             buffer,                                
     38             nBufferSize,        
     39             bIncludeSubdirectories,             
     40             FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_FILE_NAME,     
     41             &dwBytes,                         
     42             NULL,                    
     43             NULL) || GetLastError() == ERROR_INVALID_HANDLE)
     44         {
     45             break;
     46         }
     47 
     48         if(!dwBytes)
     49         {
     50             printf("Buffer overflow~~
    ");
     51         }
     52         
     53         PFILE_NOTIFY_INFORMATION record = (PFILE_NOTIFY_INFORMATION)buffer;
     54         DWORD cbOffset = 0;
     55 
     56         do
     57         {    
     58             switch (record->Action)
     59             {
     60             case FILE_ACTION_ADDED:    
     61                 printf("FILE_ACTION_ADDED:");
     62                 break;
     63             case FILE_ACTION_REMOVED:
     64                 printf("FILE_ACTION_REMOVED:");
     65                 break;
     66             case FILE_ACTION_MODIFIED:
     67                 printf("FILE_ACTION_MODIFIED:");
     68                 break;
     69             case FILE_ACTION_RENAMED_OLD_NAME:
     70                 printf("FILE_ACTION_RENAMED_OLD_NAME:");                
     71                 break;
     72 
     73             case FILE_ACTION_RENAMED_NEW_NAME:
     74                 printf("FILE_ACTION_RENAMED_NEW_NAME:");
     75                 break;
     76 
     77             default:
     78                 break;
     79             }        
     80 
     81             char fileBuffer[512];
     82 
     83             WideCharToMultiByte(CP_ACP, 0, record->FileName, record->FileNameLength, fileBuffer, record->FileNameLength, NULL, NULL);  
     84             printf(fileBuffer);
     85             printf("
    ");
     86 
     87             cbOffset = record->NextEntryOffset;
     88             record = (PFILE_NOTIFY_INFORMATION)((LPBYTE) record + cbOffset);
     89         }while(cbOffset);        
     90     }
     91 
     92     delete buffer;
     93 
     94     if(hDirectoryHandle)
     95         CloseHandle(hDirectoryHandle);
     96 }
     97 
     98 int _tmain(int argc, _TCHAR* argv[])
     99 {
    100     MonitorDir("C:\Users\larry\Desktop\新增資料夾");
     

    運行後去對監控的目錄操作~可得到類似如下的結果:

    image

  • 相关阅读:
    putty设置用key自动登录
    linux快速进入全屏命令行模式
    二维数组的指针
    vim编写Bash脚本
    使用cat命令添加或附加多行文本
    Linode中的Network Helper
    网络通信框架之retrofit
    网络通信框架之okHttp
    网络通信框架之okHttpUtils
    Volley源码分析
  • 原文地址:https://www.cnblogs.com/chechen/p/5288444.html
Copyright © 2020-2023  润新知