1. 程式人生 > >vc++ 監控指定路徑下檔案變化

vc++ 監控指定路徑下檔案變化

參考MSDN文件

https://docs.microsoft.com/zh-cn/windows/desktop/api/winbase/nf-winbase-readdirectorychangesw

https://docs.microsoft.com/zh-cn/windows/desktop/api/winnt/ns-winnt-_file_notify_information

 

具體看程式碼

 # include < iostream >
 # include < windows.h >
 # include < process.h >
 # include < tchar.h >
 # include < string >
using namespace std;
typedef void( * CHANGESCALLBACK)(const std::wstring strFileName);
/*
@ 監控指定目錄下檔案變化
@ strDirPath 需要監控的目錄
@ dwChangesType 需要監控檔案變化方式
@ onCallBack  變化後的回撥處理函式
 */
void CheckFilesChanges(const std::wstring strDirPath, DWORD dwChangesType, CHANGESCALLBACK onCallBack);
void PrintMsg(const std::wstring strFileName) {
	wprintf_s(L "new add File:\t %s\r\n", strFileName.c_str());
}
void CheckFilesChanges(const std::wstring strDirPath, DWORD dwChangesType, CHANGESCALLBACK onCallBack) {
	if (strDirPath.empty() || !onCallBack)
		return;
	HANDLE hDir = INVALID_HANDLE_VALUE;
	BYTE lpBuffer[1024];
	ZeroMemory(lpBuffer, 1024);
	DWORD cbBytes = NULL;
	BOOL isOk = FALSE;
	FILE_NOTIFY_INFORMATION * pnotify = (FILE_NOTIFY_INFORMATION * )lpBuffer;
	FILE_NOTIFY_INFORMATION * tmp;
	ZeroMemory( & lpBuffer, sizeof(FILE_NOTIFY_INFORMATION));
	hDir = CreateFile(strDirPath.c_str(), 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 == hDir)
		return;
	while (true) {
		isOk = ReadDirectoryChangesW(hDir,  & lpBuffer,
				sizeof(lpBuffer),
				TRUE,
				FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE,
				 & cbBytes,
				NULL,
				NULL);
		if (isOk) {
			tmp = pnotify;
			PWSTR fileName = nullptr;
			std::wstring strFileName;
			if (tmp->FileNameLength) {
				DWORD dwLength = tmp->FileNameLength + 1;
				fileName = new wchar_t[dwLength];
				if (fileName) {
					memset(fileName, 0, dwLength * 2);
					memcpy(fileName, tmp->FileName, dwLength * 2);
					strFileName = fileName;
				}
				if (fileName)
					delete []fileName;
			}
			if (tmp->Action == dwChangesType) {
				onCallBack(strFileName);
			}
			ZeroMemory(tmp, 1024);
			/*switch (tmp->Action){
			case FILE_ACTION_ADDED:	//當前目錄新增檔案{
			onCallBack(strFileName);
			}break;

			case FILE_ACTION_REMOVED:	//該檔案已從目錄中刪除{
			onCallBack(strFileName);
			}
			break;
			case FILE_ACTION_MODIFIED:	//該檔案已被修改。也可以是時間戳或屬性的更改{
			onCallBack(strFileName);
			}
			break;
			case FILE_ACTION_RENAMED_OLD_NAME:	//該檔案已重新命名,這是舊名稱。{
			onCallBack(strFileName);
			}
			break;
			case FILE_ACTION_RENAMED_NEW_NAME: //該檔案已重新命名,這是新名稱。{
			onCallBack(strFileName);
			}
			break;
			default:
			break;
			}*/
		}
	}
	CloseHandle(hDir);
}
unsigned int CALLBACK ThreadProc(void * arg) {
	CheckFilesChanges(_T("E:\\GoCode"), FILE_ACTION_ADDED, PrintMsg);
	return 0;
}
int main(int argc, char * argv[]) {
	HANDLE hThread = NULL;
	hThread = (HANDLE)::_beginthreadex(nullptr, NULL, ThreadProc, NULL, NULL, NULL);
	system("pause");
	return 0;
}