• 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

  • 相关阅读:
    解析大型.NET ERP系统 权限模块设计与实现
    Enterprise Solution 开源项目资源汇总 Visual Studio Online 源代码托管 企业管理软件开发框架
    解析大型.NET ERP系统 单据编码功能实现
    解析大型.NET ERP系统 单据标准(新增,修改,删除,复制,打印)功能程序设计
    Windows 10 部署Enterprise Solution 5.5
    解析大型.NET ERP系统 设计异常处理模块
    解析大型.NET ERP系统 业务逻辑设计与实现
    解析大型.NET ERP系统 多国语言实现
    Enterprise Solution 管理软件开发框架流程实战
    解析大型.NET ERP系统 数据审计功能
  • 原文地址:https://www.cnblogs.com/chechen/p/5288444.html
Copyright © 2020-2023  润新知