#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