#include <iostream>
#include <conio.h>
#include <vector>
using std::vector;
using std::cout;
using std::cin;
using std::endl;
#define pause() (_getch(),0)
#include <Windows.h>
DWORD dwFilterNotify = FILE_NOTIFY_CHANGE_FILE_NAME;
/*
FILE_NOTIFY_CHANGE_FILE_NAME |
FILE_NOTIFY_CHANGE_DIR_NAME |
FILE_NOTIFY_CHANGE_ATTRIBUTES |
FILE_NOTIFY_CHANGE_SIZE |
FILE_NOTIFY_CHANGE_LAST_WRITE |
FILE_NOTIFY_CHANGE_LAST_ACCESS |
FILE_NOTIFY_CHANGE_CREATION |
FILE_NOTIFY_CHANGE_SECURITY;
*/
int error()
{
DWORD _error = ::GetLastError();
cout<<"Error code: "<<_error<<endl;
return _error;
}
const int size_fni = 100 * sizeof(FILE_NOTIFY_INFORMATION);
struct SDir
{
OVERLAPPED Over;
BYTE *pBuffer;
SDir() {
pBuffer = new BYTE[size_fni + 1];
}
~SDir() {
delete []pBuffer;
}
};
HANDLE CreateIoCompletionPort(DWORD dwNumberOfConcurrentThreads = 1) {
return ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, dwNumberOfConcurrentThreads);
}
BOOL AssignIoCompletionPort(HANDLE hDirectory, HANDLE hExistingCompletionPort, ULONG_PTR CompletionKey) {
return
(::CreateIoCompletionPort(hDirectory, hExistingCompletionPort, CompletionKey, 0) != NULL);
}
HANDLE AssignDirectory(LPTSTR lpDirectory) {
return ::CreateFile(lpDirectory, FILE_LIST_DIRECTORY, FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL);
}
LPCSTR ExplainAction( DWORD dwAction )
{
switch (dwAction)
{
case FILE_ACTION_ADDED :
return "Added";
case FILE_ACTION_REMOVED :
return "Deleted";
case FILE_ACTION_MODIFIED :
return "Modified";
case FILE_ACTION_RENAMED_OLD_NAME :
return "Renamed From";
case FILE_ACTION_RENAMED_NEW_NAME :
return "Renamed To";
default:
return "BAD DATA";
}
}
DWORD __stdcall Thread(LPVOID lpParam)
{
DWORD dwNumberOfBytesTransferred;
HANDLE hDevice = nullptr;
SDir* pDir = nullptr;
DWORD dwBytesReturned = 0;
for(;;)
{
BOOL _error = ::GetQueuedCompletionStatus(static_cast<HANDLE>(lpParam), &dwNumberOfBytesTransferred, (ULONG_PTR*)&hDevice, (OVERLAPPED**)&pDir, INFINITE);
if(!_error) {
error();
}
FILE_NOTIFY_INFORMATION *pBuffer = (FILE_NOTIFY_INFORMATION*)pDir->pBuffer;
char*pChar = new char[pBuffer->FileNameLength / 2+1];
WideCharToMultiByte( CP_ACP, 0,
pBuffer->FileName,
pBuffer->FileNameLength,
pChar,
pBuffer->FileNameLength / 2,
NULL, NULL);
pChar[ pBuffer->FileNameLength / 2 ] = 0;
cout<<pChar<<' '<<ExplainAction(pBuffer->Action)<<endl;
delete pChar;
/*
*/
memset((void*)&pDir->Over, 0, sizeof(OVERLAPPED));
//memset((void*)pDir->pBuffer, 0, 100);
_error = ::ReadDirectoryChangesW(
hDevice, pDir->pBuffer, size_fni, FALSE, dwFilterNotify, &dwBytesReturned, &pDir->Over, 0 );
// parsing
Sleep(1000);
}
return 0;
}
HANDLE CreateThread(HANDLE hIOCP)
{
DWORD dwThreadId = 0;
return ::CreateThread(NULL, 0, Thread, hIOCP, 0, &dwThreadId);
}
int main()
{
HANDLE hIOCP = CreateIoCompletionPort();
DWORD dwBytesReturned = 0;
SDir *pDir = new SDir;
memset((void*)&pDir->Over, 0, sizeof(OVERLAPPED));
if(!hIOCP) {
return error();
}
HANDLE hThread = CreateThread(hIOCP);
if(!hThread) {
return error();
}
HANDLE hDirectory = nullptr;
hDirectory = AssignDirectory(L"C:\\space\\1");
if(!AssignIoCompletionPort(hDirectory, hIOCP, (ULONG_PTR)hDirectory))
{
return error();
}
BOOL _error = ::ReadDirectoryChangesW(
hDirectory, pDir->pBuffer, size_fni, FALSE, dwFilterNotify, &dwBytesReturned, &pDir->Over, 0 );
if(!_error)
{
return error();
}
hDirectory = AssignDirectory(L"C:\\space\\2");
if(!AssignIoCompletionPort(hDirectory, hIOCP, (ULONG_PTR)hDirectory))
{
return error();
}
//cout<< hDirectory << endl;
_error = ::ReadDirectoryChangesW(
hDirectory, pDir->pBuffer, size_fni, FALSE, dwFilterNotify, &dwBytesReturned, &pDir->Over, 0 );
WaitForSingleObject(hThread, INFINITE);
return pause();
}
Проблема в следующем:
наблюдение я ввиду за директорией "C:\\space\\1"
1. Если я кидаю в нее файлы: 29-00014.IN, 29-00014.txt, 29-00015.IN, 29-00015.txt, то 1 или 2 файла не фиксируются функцией( не выводятся на консоль). С удалением тоже самое.
2. Иногда бывает когда я бросаю 4 файла в папу то вывод будет типа этого
"29-00014.txt" "29-00014.txt" "29-00014.txt" "29-00014.IN"
Вывод идет в Thread