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