国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - C/C++ - VC++文件監(jiān)控之ReadDirectoryChangesW

VC++文件監(jiān)控之ReadDirectoryChangesW

2021-07-26 12:08C++教程網(wǎng) C/C++

文章主要介紹文件監(jiān)控的另一種實(shí)現(xiàn)方式,利用ReadDirectoryChangesW來實(shí)現(xiàn)文件的監(jiān)控,希望對大家有幫助

我這里只介紹采用ReadDirectoryChangesW對文件目錄實(shí)施監(jiān)控

關(guān)鍵代碼

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
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\r\n");
    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 (添加文件)- \r\n");
        break;
      case FILE_ACTION_REMOVED:
        dlg->m_edit.ReplaceSel("Directory/File removed (刪除文件)- \r\n");
        break;
      case FILE_ACTION_MODIFIED:
        dlg->m_edit.ReplaceSel("Directory/File modified (修改文件內(nèi)容)- \r\n");
        break;
      case FILE_ACTION_RENAMED_OLD_NAME:
        dlg->m_edit.ReplaceSel("Directory/File old name (修改文件名字)- \r\n");
        break;
      case FILE_ACTION_RENAMED_NEW_NAME:
        dlg->m_edit.ReplaceSel("Directory/File new name - \r\n");
        break;
      default:
        break;
      }
    }
  }

FILE_NOTIFY_INFORMATION //可以確定是那個(gè)文件進(jìn)行的修改

typedef struct _FILE_NOTIFY_INFORMATION {
DWORD NextEntryOffset;
DWORD Action;//動(dòng)作
DWORD FileNameLength;//文件名字的長度
WCHAR FileName[1];//文件名字
} FILE_NOTIFY_INFORMATION,
*PFILE_NOTIFY_INFORMATION;

ReadDirectoryChangesW 返回類型(見MSDN)

 

Value Meaning

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.

 

效果如下:

VC++文件監(jiān)控之ReadDirectoryChangesW

不足的地方:

只能檢測到指定目錄和下一級目錄,超過目錄級數(shù),該函數(shù)檢測不到。

ReadDirectoryChangesW 監(jiān)控文件夾 (一個(gè)簡單的監(jiān)控示例程序)

.h文件

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// .h文件
#pragma once
 
typedef void (*PFN_NotifyAction)(DWORD dwAction, LPWSTR szFile, DWORD dwLength);
 
class CDirectoryWatch
{
public:
    CDirectoryWatch(void);
    virtual ~CDirectoryWatch(void);
 
public:
    BOOL StartDirectoryWatch(LPCTSTR lpszDirectory, PFN_NotifyAction pFn_NotifyAction);
    BOOL StopDirectoryWatch(void);
 
private:
    static UINT __cdecl ThreadProc(LPVOID lParam);
    static UINT __cdecl DirectoryWatch(LPVOID lParam);
 
private:
    HANDLE m_hFile;
    CWinThread* m_pThread;
    TCHAR m_szDirectory[MAX_PATH];
};

.cpp文件

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

測試代碼

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
// 測試代碼
 
#include "stdafx.h"
 
#include "DirectoryWatch.h"
 
void NotifyAction(DWORD dwAction, LPWSTR szFile, DWORD dwLength)
{
    switch(dwAction)
    {
    case FILE_ACTION_ADDED:
        wprintf(L"FILE_ACTION_ADDED: \n\t");
        break;
 
    case FILE_ACTION_REMOVED:
        wprintf(L"FILE_ACTION_REMOVED: \n\t");
        break;
 
    case FILE_ACTION_MODIFIED:
        wprintf(L"FILE_ACTION_MODIFIED: \n\t");
        break;
 
    case FILE_ACTION_RENAMED_OLD_NAME:
        wprintf(L"FILE_ACTION_RENAMED_OLD_NAME: \n\t");
        break;
 
    case FILE_ACTION_RENAMED_NEW_NAME:
        wprintf(L"FILE_ACTION_RENAMED_NEW_NAME: \n\t");
        break;
 
    default:
        break;
    }
    WCHAR szPath[MAX_PATH] = {0};
    wmemcpy(szPath, szFile, min(dwLength, MAX_PATH));
    wprintf(L"%s\n", szPath);
}
 
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
    CDirectoryWatch watch;
    wprintf(L"Start Directory Watch ...\n");
    watch.StartDirectoryWatch(_T("F:\\11"), NotifyAction);
    Sleep(30 * 1000);  
    watch.StopDirectoryWatch();
    wprintf(L"Stop Directory Watch ...\n");
 
    Sleep(10 * 1000);
 
    wprintf(L"Start Directory Watch ...\n");
    watch.StartDirectoryWatch(_T("F:\\11"), NotifyAction);
    Sleep(30 * 1000);  
    watch.StopDirectoryWatch();
    wprintf(L"Stop Directory Watch ...\n");
    Sleep(30 * 1000);
    wprintf(L"Process Exit ...\n");
    return 0;
}

效果如下圖所示:

VC++文件監(jiān)控之ReadDirectoryChangesW

使用ReadDirectoryChangesW API監(jiān)控文件系統(tǒng)的改變

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

VC++文件監(jiān)控之ReadDirectoryChangesW

并加入Windows.h的標(biāo)頭檔

#include "Windows.h"

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

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

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

 

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

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

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

取得監(jiān)控的目錄Handle后,將其帶入ReadDirectoryChangesw API,順帶帶入像是回傳變動(dòng)資料的Buffer空間、與要監(jiān)控的變動(dòng)類型等必要參數(shù)。像是下面這樣:

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

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

若是運(yùn)行沒發(fā)生問題,變動(dòng)的資料會存放在當(dāng)初塞進(jìn)去的存儲空間,該空間的資料其實(shí)是FILE_NOTIFY_INFORMATION structure的型態(tài)存在,因此我們可將存儲空間的資料轉(zhuǎn)換成PFILE_NOTIFY_INFORMATION。裡面的Action是我們所關(guān)注的變動(dòng)類型,F(xiàn)ileName是變動(dòng)的檔案名稱,檔案名稱的部分是沒有結(jié)尾符號的,必須要搭配FileNameLength去截取。另外變動(dòng)的資料有時(shí)候不止一筆,因此我們必須在這邊用迴圈搭配NextEntryOffset去重覆運(yùn)行處理流程,處理所有變動(dòng)的資料。

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

這邊示范一個(gè)簡易的使用范例,實(shí)際使用時(shí)最好還是搭配執(zhí)行緒處理:

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

運(yùn)行后去對監(jiān)控的目錄操作~可得到類似如下的結(jié)果:

VC++文件監(jiān)控之ReadDirectoryChangesW

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 国产在线中文字幕 | 中文字幕在线观看一区 | 亚洲第一av网站 | av免费在线观看网站 | 91精品国产91久久久久久黑人 | 精品一区二区久久久久久久网站 | 午夜视频一区二区三区 | 欧洲精品 | 欧美1区2区3区 | 亚洲国产精品一区二区久久 | 欧洲色视频 | 日韩精品免费在线观看 | 国产高清一区 | 亚洲精品一区二区三区蜜桃久 | 国产一区二区精品 | 99综合 | 国产精品久久久久桃色tv | 日韩欧美在线视频 | 在线观看三级网站 | 久久久精品日本 | 亚洲国产精品久久久久婷婷老年 | 中文字幕 国产精品 | av一二| 国产精品一区久久久 | 欧美1区2区3区 | jizz中国zz女人18高潮 | 精品国产免费久久久久久尖叫 | 福利视频网| 日韩在线播放一区二区 | 亚洲视频区 | 最新av在线 | 久草中文在线 | 嫩呦国产一区二区三区av | 国产精品久久久久免费a∨ 欧美黄色精品 | 日本中文字幕久久 | 久久精品国产亚洲一区二区三区 | 欧美激情综合五月色丁香小说 | 黄工厂精品免费观看 | 一本色道精品久久一区二区三区 | 欧美国产一区二区三区 | 在线免费成人 |