WIN32 监控目录

/*
Monitor File Change Infomation
---Completion Port Module
Monitor Example 1.0  适用于监控一个目录


Author: yaliao [lya_118@163.com]
*/


#include <windows.h>
#include <conio.h>
#include <iostream>
#include <string>


#define MAX_BUFFER  4096
//
//自定义结构,即“完成键”(单句柄数据)
//
typedef struct _PER_IO_CONTEXT
{
OVERLAPPED ol;
HANDLE hDir;
CHAR lpBuffer[MAX_BUFFER];
_PER_IO_CONTEXT* pNext;
}PER_IO_CONTEXT, *PPER_IO_CONTEXT;


PPER_IO_CONTEXT g_pIContext;


#if 0
typedef BOOL(WINAPI *lpReadDirectoryChangesW)(HANDLE,
LPVOID,
DWORD,
BOOL,
DWORD,
LPDWORD,
LPOVERLAPPED,
LPOVERLAPPED_COMPLETION_ROUTINE);
lpReadDirectoryChangesW ReadDirectoryChangesW = NULL;
#endif


HANDLE g_hIocp;
HANDLE g_hDir;


DWORD WINAPI CompletionRoutine(LPVOID lpParam);
void FileActionRoutine(PFILE_NOTIFY_INFORMATION pfi);
TCHAR szDirectory[] = L"C:\\Users\\Administrator\\Desktop\\Monitor\\Monitor";


DWORD nBufferLength = 256;
CHAR lpBuffer[256] = {0};


void main()
{
GetCurrentDirectoryA(nBufferLength, lpBuffer);


HANDLE hRet;
HANDLE hThread;


g_hIocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
if (NULL == g_hIocp)
{
std::cout << "CreateIoCompletionPort Failed: " << GetLastError() << std::endl;
return;
}


std::cout << "monitor directory is: " << szDirectory << std::endl;
g_hDir = CreateFile(szDirectory,
FILE_LIST_DIRECTORY,
FILE_SHARE_READ |
FILE_SHARE_WRITE |
FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS |
FILE_FLAG_OVERLAPPED,
NULL);


if (NULL == g_hDir)
{
std::cout << "CreateFile Failed: " << GetLastError() << std::endl;
CloseHandle(g_hIocp);
return;
}


HINSTANCE hInst = LoadLibrary(L"Kernel32.DLL");
if (!hInst)
{
std::cout << "LoadLibrary Failed: " << GetLastError() << std::endl;
CloseHandle(g_hIocp);
CloseHandle(g_hDir);
return;
}


#if 0
ReadDirectoryChangesW = (lpReadDirectoryChangesW)GetProcAddress(hInst, "ReadDirectoryChangesW");//获取DLL函数入口
#endif


FreeLibrary(hInst);


SYSTEM_INFO SysInfo;
GetSystemInfo(&SysInfo);
for (int i = 0; i < (int)SysInfo.dwNumberOfProcessors; i++)
{
hThread = CreateThread(NULL, 0, CompletionRoutine, NULL, 0, NULL);
if (NULL == hThread)
{
std::cout << "CreateThread Failed: " << GetLastError() << std::endl;
CloseHandle(g_hIocp);
CloseHandle(g_hDir);
return;
}
CloseHandle(hThread);
}


g_pIContext = (PPER_IO_CONTEXT)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PER_IO_CONTEXT));
if (NULL == g_pIContext)
{
std::cout << "HeapAlloc Failed: " << GetLastError() << std::endl;
PostQueuedCompletionStatus(g_hIocp, 0, NULL, NULL);
CloseHandle(g_hIocp);
CloseHandle(g_hDir);
return;
}


g_pIContext->hDir = g_hDir;
ZeroMemory(&(g_pIContext->ol), sizeof(OVERLAPPED));
ZeroMemory(g_pIContext->lpBuffer, MAX_BUFFER);
g_pIContext->pNext = NULL;


hRet = CreateIoCompletionPort(g_hDir, g_hIocp, (ULONG_PTR)g_pIContext, 0);
if (NULL == hRet)
{
std::cout << "CreateIoCompletionPort Failed: " << GetLastError() << std::endl;
PostQueuedCompletionStatus(g_hIocp, 0, NULL, NULL);
CloseHandle(g_hIocp);
CloseHandle(g_hDir);
HeapFree(GetProcessHeap(), 0, g_pIContext);
return;
}


DWORD nBytes = 0;
BOOL  bRet = FALSE;


bRet = ReadDirectoryChangesW(g_pIContext->hDir,
g_pIContext->lpBuffer,
MAX_BUFFER,
TRUE,
//FILE_NOTIFY_CHANGE_FILE_NAME |
//FILE_NOTIFY_CHANGE_DIR_NAME |
FILE_NOTIFY_CHANGE_ATTRIBUTES ,
//FILE_NOTIFY_CHANGE_SIZE |
//FILE_NOTIFY_CHANGE_LAST_ACCESS |
//FILE_NOTIFY_CHANGE_CREATION |
//FILE_NOTIFY_CHANGE_SECURITY |
//FILE_NOTIFY_CHANGE_LAST_WRITE,
&nBytes,
&(g_pIContext->ol),
NULL);


if (!bRet)
{
std::cout << "ReadDirectoryChangesW Failed: " << GetLastError() << std::endl;
PostQueuedCompletionStatus(g_hIocp, 0, NULL, NULL);
CloseHandle(g_hIocp);
CloseHandle(g_hDir);
HeapFree(GetProcessHeap(), 0, g_pIContext);
return;
}


std::cout << "Enter q to exit: " << std::endl;
while (getch() != 'q');


PostQueuedCompletionStatus(g_hIocp, 0, NULL, NULL);
CloseHandle(g_hIocp);
CloseHandle(g_hDir);
HeapFree(GetProcessHeap(), 0, g_pIContext);
std::cout << "Main thread will exit " << std::endl;
getch();
}


DWORD WINAPI CompletionRoutine(LPVOID lpParam)
{
DWORD dwBytes;
PPER_IO_CONTEXT pIContext = NULL;
LPOVERLAPPED pOL = NULL;
PFILE_NOTIFY_INFORMATION pfi = NULL;
BOOL bRet;
DWORD cbOffset;
DWORD nBytes;
while (true)
{
bRet = GetQueuedCompletionStatus(g_hIocp, &dwBytes, (PULONG_PTR)&pIContext, &pOL, INFINITE);


if (bRet)
{
if (NULL == pIContext)
{
std::cout << "CompletionRoutine thread exit " << std::endl;
return 0;
}


pfi = (PFILE_NOTIFY_INFORMATION)pIContext->lpBuffer;


do
{
try
{
switch (pfi->Action)
{
case FILE_ACTION_MODIFIED: //The file was modified. This can be a change in the time stamp or attributes.
//std::cout << "FILE_ACTION_MODIFIED: ";
FileActionRoutine(pfi);
break;
case FILE_ACTION_ADDED: //The file was added to the directory.
std::cout << "FILE_ACTION_ADDED: ";
FileActionRoutine(pfi);
break;
case FILE_ACTION_REMOVED: //The file was removed from the directory.
std::cout << "FILE_ACTION_REMOVED: ";
FileActionRoutine(pfi);
break;
case FILE_ACTION_RENAMED_OLD_NAME: //The file was renamed and this is the old name.
std::cout << "FILE_ACTION_RENAMED_OLD_NAME: ";
FileActionRoutine(pfi);
break;
case FILE_ACTION_RENAMED_NEW_NAME: //The file was renamed and this is the new name.
std::cout << "FILE_ACTION_RENAMED_NEW_NAME: ";
FileActionRoutine(pfi);
break;
default:
break;
}


cbOffset = pfi->NextEntryOffset;//一次消息中包含了多个文件变化的信息吗?
pfi = (PFILE_NOTIFY_INFORMATION)((LPBYTE)pfi + cbOffset);
}
catch (...)
{
LPVOID lpMsgBuf;
FormatMessage( //把错误消息格式化
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(), //错误消息
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR)&lpMsgBuf, //格式化后的错误消息
0,
NULL
);
std::cout << "CompletionRoutine Exception = " << lpMsgBuf << std::endl;
LocalFree(lpMsgBuf);
}
} while (cbOffset);
}


g_pIContext->hDir = g_hDir;
ZeroMemory(&(g_pIContext->ol), sizeof(OVERLAPPED));
ZeroMemory(g_pIContext->lpBuffer, MAX_BUFFER);
g_pIContext->pNext = NULL;


nBytes = 0;
bRet = FALSE;


bRet = ReadDirectoryChangesW(g_pIContext->hDir,
g_pIContext->lpBuffer,
MAX_BUFFER,
TRUE,
//FILE_NOTIFY_CHANGE_FILE_NAME |
//FILE_NOTIFY_CHANGE_DIR_NAME |
FILE_NOTIFY_CHANGE_ATTRIBUTES ,
//FILE_NOTIFY_CHANGE_SIZE |
//FILE_NOTIFY_CHANGE_LAST_ACCESS |
//FILE_NOTIFY_CHANGE_CREATION |
//FILE_NOTIFY_CHANGE_SECURITY |
//FILE_NOTIFY_CHANGE_LAST_WRITE,
&nBytes,
&(g_pIContext->ol),
NULL);


if (!bRet)
{
std::cout << "ReadDirectoryChangesW Failed: " << GetLastError() << std::endl;
return 0;
}
}
}


/* ************************************
*DWORD ShowFileTime(PFILETIME lptime)
* 功能    轮换文件时间,将打印
*
* 参数    PFILETIME lptime,指向文件时间的指针
*
* 返回值 0
**************************************/
DWORD ShowFileTime(PFILETIME lptime)
{
//文件时间结构
FILETIME ftLocal;
//系统时间结构
SYSTEMTIME st;
//调整为系统所在时区的时间
FileTimeToLocalFileTime(
lptime,
&ftLocal
);
//将文件时间转换为SYSTEMTIME格式,便于显示。
FileTimeToSystemTime(
&ftLocal,
&st
);
//显示时间信息字符串
printf("%4d年%.2d月%#02d日,%.2d:%.2d:%.2d\n",
st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);


return 0;
}


void FileActionRoutine(PFILE_NOTIFY_INFORMATION pfi)
{
CHAR szFileName[MAX_PATH];
memset(szFileName, '\0', sizeof(szFileName));
WideCharToMultiByte(CP_ACP, //ANSI码
0,
pfi->FileName,   //待转换的字符串
pfi->FileNameLength / 2,
szFileName,     //转换后的字符串
MAX_PATH,
NULL,
NULL);


WIN32_FILE_ATTRIBUTE_DATA wfad = {0};
//printf("文件:%s\n", szFileName);


std::string fullpath = lpBuffer;
fullpath = fullpath + "\\";
fullpath = fullpath + szFileName;


if (GetFileAttributesExA(fullpath.c_str(), GetFileExInfoStandard, &wfad))
{
if (pfi->NextEntryOffset != 0 || (wfad.nFileSizeHigh == 0 && wfad.nFileSizeLow == 0))
{
ShowFileTime(&wfad.ftLastWriteTime);
std::cout << fullpath << std::endl;
}
}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值