欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

 更新時間:2019年04月07日 22:46:53   投稿:mdxy-dxy  
文章主要介紹文件監(jiān)控的另一種實(shí)現(xiàn)方式,利用ReadDirectoryChangesW來實(shí)現(xiàn)文件的監(jiān)控,希望對大家有幫助

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

關(guān)鍵代碼

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 //可以確定是那個文件進(jìn)行的修改

typedef struct _FILE_NOTIFY_INFORMATION {
DWORD NextEntryOffset;
DWORD Action;//動作
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.

效果如下:

不足的地方:

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

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

.h文件

// .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文件

// .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;
}

測試代碼

// 測試代碼
 
#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;
}

效果如下圖所示:

使用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。

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

#include "Windows.h"

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

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必須帶入八個參數(shù),hDirectory帶入的是要監(jiān)控的目錄Handle、lpBuffer帶入的是用來回傳變動資料的空間、nBufferLength是lpBuffer空間的大小、bWatchSubtree是指定是否偵測子目錄、dwNotifyFilter是指定監(jiān)控的目錄有哪些動作時需要通知、lpBytesReturned是用來回傳變動資料內(nèi)含的長度、lpOverlapped可用來在非同步環(huán)境下使用重疊IO用、lpCompletionRoutine則是當(dāng)監(jiān)控完成或取消時所呼叫的回調(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函式必須要帶入的第一個參數(shù)是要監(jiān)控的目錄Handle,所以我們必須透過CreateFile API取得要監(jiān)控的目錄Handle,像是下面這樣:

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,順帶帶入像是回傳變動資料的Buffer空間、與要監(jiān)控的變動類型等必要參數(shù)。像是下面這樣:

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");
}

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

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

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

// 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é)果:

相關(guān)文章

  • 基于c++ ege圖形庫實(shí)現(xiàn)五子棋游戲

    基于c++ ege圖形庫實(shí)現(xiàn)五子棋游戲

    這篇文章主要為大家詳細(xì)介紹了基于c++ ege圖形庫實(shí)現(xiàn)五子棋游戲,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-12-12
  • vscode使用官方C/C++插件無法進(jìn)行代碼格式化問題

    vscode使用官方C/C++插件無法進(jìn)行代碼格式化問題

    這篇文章主要介紹了vscode使用官方C/C++插件無法進(jìn)行代碼格式化問題,本文通過截圖實(shí)例代碼相結(jié)合給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-04-04
  • 深入講解Socket原理

    深入講解Socket原理

    這篇文章深入的講解Socket原理,并附帶實(shí)例代碼。小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2021-12-12
  • 基于C++實(shí)現(xiàn)信息管理系統(tǒng)

    基于C++實(shí)現(xiàn)信息管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了基于C++實(shí)現(xiàn)信息管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • 模擬鼠標(biāo)事件的實(shí)現(xiàn)思路及代碼

    模擬鼠標(biāo)事件的實(shí)現(xiàn)思路及代碼

    這篇文章主要介紹了模擬鼠標(biāo)事件的實(shí)現(xiàn)思路及代碼,有需要的朋友可以參考一下
    2013-12-12
  • C語言 文件的隨機(jī)讀寫詳解及示例代碼

    C語言 文件的隨機(jī)讀寫詳解及示例代碼

    本文主要介紹C語言 文件的隨機(jī)讀寫,這里整理了相關(guān)資料及示例代碼以便大家學(xué)習(xí)參考,學(xué)習(xí)此部分內(nèi)容的朋友可以參考下
    2016-08-08
  • c語言中十進(jìn)制轉(zhuǎn)二進(jìn)制顯示小工具的實(shí)現(xiàn)代碼

    c語言中十進(jìn)制轉(zhuǎn)二進(jìn)制顯示小工具的實(shí)現(xiàn)代碼

    本篇文章是對c語言中十進(jìn)制轉(zhuǎn)二進(jìn)制顯示小工具的實(shí)現(xiàn)代碼進(jìn)行了詳細(xì)的分析的介紹,需要的朋友參考下
    2013-05-05
  • C++實(shí)現(xiàn)小型復(fù)數(shù)計(jì)算器

    C++實(shí)現(xiàn)小型復(fù)數(shù)計(jì)算器

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)小型復(fù)數(shù)計(jì)算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-06-06
  • Socket通信原理和實(shí)踐

    Socket通信原理和實(shí)踐

    本文詳細(xì)講解了Socket通信原理和實(shí)踐,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-01-01
  • C/C++ 宏詳細(xì)解析

    C/C++ 宏詳細(xì)解析

    關(guān)于宏的一些語法問題,可以在google上找到。相信我,你對于宏的了解絕對沒你想象的那么多。如果你還不知道#和##,也不知道prescan,那么你肯定對宏的了解不夠
    2013-09-09

最新評論