码迷,mamicode.com
首页 > 其他好文 > 详细

ReadDirectoryChanges实现监控文件夹

时间:2015-05-27 17:19:56      阅读:381      评论:0      收藏:0      [点我收藏+]

标签:readdirectorychanges   windows   

#include <tchar.h>
#include <stdio.h>
#include <Windows.h>
#include <assert.h>
#include <locale>

#pragma warning(disable: 4995)
#pragma warning(disable: 4996)
#include "adkprecomp.h"
#include "adkfile.h"

int parse_notify_information(const wchar_t *src_dir, const wchar_t *dst_dir, const PFILE_NOTIFY_INFORMATION ctx)
{
	PFILE_NOTIFY_INFORMATION fcinfo = ctx;

	wchar_t file_name[MAX_PATH] = {0};
	wchar_t src_file[MAX_PATH] = {0};
	wchar_t dst_file[MAX_PATH] = {0};

	if (!fcinfo) return -1;

	do 
	{
		memset(file_name, L'\0', sizeof(file_name));
		memcpy_s(file_name, sizeof(file_name), fcinfo->FileName, fcinfo->FileNameLength);

		swprintf_s(src_file, _countof(src_file), L"%ws%ws", src_dir, file_name);
		swprintf_s(dst_file, _countof(dst_file), L"%ws%ws", dst_dir, file_name);
		AdkCreateDirectoryW(dst_file);

		switch (fcinfo->Action)
		{
		case FILE_ACTION_ADDED:
			wprintf_s(L"add file %ws \r\n", file_name);
			break;
		case FILE_ACTION_MODIFIED:
			wprintf_s(L"modified file %ws \r\n", file_name);

			// 此处可能可能出现拷贝失败错误码为32的错误
			// 解决办法:使用while循环重试CopyFileW
			//
			while(!CopyFileW(src_file, dst_file, FALSE))
			{
				Sleep(10);
			}

			break;
		case FILE_ACTION_REMOVED:
			wprintf_s(L"removed file %ws \r\n", file_name);
			break;
		case FILE_ACTION_RENAMED_NEW_NAME:
			wprintf_s(L"renamed new file %ws \r\n", file_name);
			break;
		case FILE_ACTION_RENAMED_OLD_NAME:
			wprintf_s(L"renamed old file %ws \r\n", file_name);
			break;
		default:
			//assert(!L"unknown action type!!!");
			break;
		}

		fcinfo = (PFILE_NOTIFY_INFORMATION)((unsigned long)fcinfo + fcinfo->NextEntryOffset);

	} while (fcinfo->NextEntryOffset);

	return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
	HANDLE change_handle = INVALID_HANDLE_VALUE;

	PFILE_NOTIFY_INFORMATION fcinfo = NULL;

	OVERLAPPED overlapped = {0};

	wchar_t apppath[MAX_PATH] = {0};
	wchar_t config_file[MAX_PATH] = {0};
	wchar_t src_dir[MAX_PATH] = {0};
	wchar_t dst_dir[MAX_PATH] = {0};

	char buf[2048] = {0};			// 这里的大小需要足够大,可改成动态申请较大的内存空间

	unsigned long wait_ret = 0;
	unsigned long return_size = 0;
	unsigned long error_code = 0;

	setlocale(LC_ALL, "chs");

	GetModuleFileNameW(NULL, apppath, _countof(apppath));
	apppath[wcslen(apppath) - wcslen(wcsrchr(apppath, L'\\')) + 1] = L'\0';
	
	swprintf_s(config_file, _countof(config_file), L"%ws%ws", apppath, L"fmonitor.ini");

	GetPrivateProfileStringW(L"dir", L"src", NULL, src_dir, _countof(src_dir), config_file);
	GetPrivateProfileStringW(L"dir", L"dst", NULL, dst_dir, _countof(dst_dir), config_file);
	if (src_dir[wcslen(src_dir) - 1] != L'\\')
	{
		wcscat_s(src_dir, _countof(src_dir), L"\\");
	}
	if (dst_dir[wcslen(dst_dir) - 1] != L'\\')
	{
		wcscat_s(dst_dir, _countof(dst_dir), L"\\");
	}
	AdkCreateDirectoryW(dst_dir);

	wprintf_s(L"src_dir = %ws \r\ndst_dir = %ws \r\n", src_dir, dst_dir);

	do 
	{
		overlapped.hEvent = CreateEventW(NULL, TRUE, FALSE, L"stop_monitor_event_name");
		assert(overlapped.hEvent);

		change_handle = CreateFileW(
			src_dir, 
			FILE_LIST_DIRECTORY, 
			FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, 
			NULL, 
			OPEN_EXISTING, 
			FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, 
			NULL
			);
		if (change_handle == INVALID_HANDLE_VALUE)
		{
			assert(0);
			break;
		}

		while(1)
		{
			wprintf_s(L"waitting change ... \r\n");

			memset(buf, '\0', sizeof(buf));

			if (!ReadDirectoryChangesW(
				change_handle, 
				buf, 
				sizeof(buf), 
				TRUE, 
				FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_SIZE,	// 监控文件大小的变化 
				&return_size, 
				&overlapped, 
				NULL
				))
			{
				error_code = GetLastError();
				Sleep(10);
				continue;
			}

			if (!GetOverlappedResult(change_handle, &overlapped, &return_size, TRUE))
			{
				error_code = GetLastError();
				Sleep(10);
				continue;
			}
			if(overlapped.Internal != 0)
			{
				wprintf_s(L"stoped monitor!! \r\n");
				break;
			}
			if(return_size == 0)	// buf缓存太小将导致retrun_size == 0, 详细见MSDN说明
			{
				continue;
			}

			parse_notify_information(src_dir, dst_dir, (PFILE_NOTIFY_INFORMATION)buf);
		}

	} while (0);

	CloseHandle(overlapped.hEvent);
	CloseHandle(change_handle);
	change_handle = INVALID_HANDLE_VALUE;

	return 0;
}

实现监控文件夹中的文件变化,并将文件拷贝出来

有些API如AdkMalloc等,为自主实现的库,需要AdkPrecomp.h等头文件,可使用其它API代替


ReadDirectoryChanges实现监控文件夹

标签:readdirectorychanges   windows   

原文地址:http://blog.csdn.net/liu_si_yan/article/details/46049169

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!