ReadDirectoryChanges实现监控文件夹

#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代替

时间: 2024-10-05 07:35:48

ReadDirectoryChanges实现监控文件夹的相关文章

Storm监控文件夹变化 统计文件单词数量

监控指定文件夹,读取文件(新文件动态读取)里的内容,统计单词的数量. FileSpout.java,监控文件夹,读取新文件内容 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

.Net 监控文件夹是否有新文件生成,并确认文件没有被其他程序占用

监控文件夹测试程序: 1 using System; 2 using System.Collections.Generic; 3 using System.IO; 4 using System.Linq; 5 using System.Text; 6 using System.Threading; 7 using System.Threading.Tasks; 8 9 namespace FileSystemWatcherTest 10 { 11 class Program 12 { 13 st

Python 的 pyinotify 模块 监控文件夹和文件的变动

官方参考: https://github.com/seb-m/pyinotify/wiki/Events-types https://github.com/seb-m/pyinotify/wiki/Install 最近在网上看到python有个pyinotify模块,其中他们可以监控文件夹内的文件的创建,修改,读取,删除等系列操作,我修改了下,添加了可以吧操作记录写到日志里的一点方法,下面就贴出代码了给大家分享下:#!/usr/bin/env python ? 01 02 03 04 05 06

多线程监控文件夹,FlieSystemWatcher,并使用共享函数

发表于: 2011-01-06 09:55:47 C# code ? 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

DotNetCore跨平台~Quartz热部署的福音~监控文件夹的变化

回到目录 在DotNetCore出来之后,同时也使用了quartz进行调度中心的设计,将它做到docker里方便部署,在之前的quartz版本里支持配置文件的方式,而现在不支持了,我们应该去想一下,为什么不去支持配置文件?当然大叔也为配置文件设计了支持的方式,但我们还是应该想想作者为什么不去支持配置? 热支持,服务发现? 和上面两个概念可能有点关系,热插拔很容易理解,就是把dll模块放到正在运行的项目时,它可以直接启动,这个功能对调度中心来说,很是必要,因为你可能需要按着不同的功能设计一些服务j

C#监控文件夹变化

当需要监控某一文件,FileSystemWatcher类提供了Created, Deleted,Rename等事件. 就拿FileSystemWatcher的Created事件来说,该事件类型是FileSystemEventHandler. public delgate void FileSystemEventHandler(Object sender, FileSystemEventArgs e) ○ sender表示事件的发起者○ e表示事件参数 在C盘创建temp文件夹. 客户端. cla

delphi监控文件夹

(****************************************** 文件和目录监控 当磁盘上有文件或目录操作时,产生事件 使用方法: 开始监控: PathWatch(Self.Handle, 'C:\FtpFolder'); 解除监控:PathWatch(-1); 在窗体中加消息监听 private { Private declarations } procedure MsgListern(var Msg:TMessage);message WM_SHNOTIFY; 实现:

C# FileSystemWatcher 在监控文件夹和文件时的用法

概述 最近学习FileSystemWatcher的用法,它主要是监控一个文件夹,当文件夹内的文件要是有更改就要记录下来,我就整理下我对FileSystemWatcher 的理解和用法. FileSystemWatcher 用法 在应用FileSystemWatcher对象之前,你必须了解这个对象的一些基本属性和事件.毫无疑问,这个对象的最重要的属性为“EnableRaisingEvents”属性. 这个属性决定对象在收到改变通知时是否提交事件.如果EnableRaisingEvents属性设为假

使用FileSystemWatcher监控文件夹及文件

引言 这一周主要精力集中学习一个同事开发的本地文件搜索项目上,其中客户端添加共享文件时主要是使用FileSystemWatcher 监控文件,并在各种事件发生时向服务器发送消息. 解决方法 FileSystemWatcher类以前也使用过,没有太仔细去观察,这次使用时才发现其事件提示会很有趣: a):当你添加文件或文件夹时,会触发Created事件,然后修改默认文件夹或文件名称再触发Changed事件. b):复制或移动文件夹文件时则是触发Created事件. c):删除文件夹或文件时触发Del