admin管理员组文章数量:1336631
I have implemented a program that traces changes in a given folder using ReadDirectoryChangesW
in overlapped mode with a completion routine. It works good.
I am planning to reconstruct it to make a more universal library.
When the completion routine cr
called, and file changes are displayed, I need to continue tracing: see line DoRDC = true; // RESTART WATCHING
.
It was possible in the current version, because it run in a loop while (_kbhit() == 0) {
, but after reconstruction I will eliminate this loop.
WatchDirectory
will call ReadDirectoryChangesW
at first only.
My question is: how should I restart the tracing inside cr
?
Will it be correct to call ReadDirectoryChangesW
inside the completion routine cr
?
But it may cause call of cr
when the previous call was not finished...
May be there is a way to tell ReadDirectoryChangesW
not to stop tracing ?
My code is below. The main function - WatchDirectory();
LPVOID lpBuffer = NULL;
bool DoRDC = true;
VOID WINAPI cr(DWORD dwErrorCode,
DWORD dwNumberOfBytesTransfered,
LPOVERLAPPED lpOverlapped) {
// Completion routine
DoRDC = true; // RESTART WATCHING
std::wcout << L" ------------- lpCompletionRoutine --------------- " << std::endl;
std::wcout << L" ErrCode = " << dwErrorCode
<< L" BytesTransferred = " << dwNumberOfBytesTransfered << std::endl;
if (dwErrorCode != 0) {
return;
}
std::wcout << L"..............." << std::endl;
// simply display dir changes
DisplayFileInfo(lpBuffer, dwNumberOfBytesTransfered);
}
bool WatchDirectory(LPTSTR lpDir)
{
// AFTER RECONSTRUCTION WILL CALL ReadDirectoryChangesW 1 TIME WITHOUT A LOOP
DWORD dwWaitStatus;
HANDLE dwChangeHandles[2];
TCHAR lpDrive[4];
TCHAR lpFile[_MAX_FNAME];
TCHAR lpExt[_MAX_EXT];
HANDLE hDir = INVALID_HANDLE_VALUE;
std::wcout << L"3_Watching for: " << lpDir << std::endl;
_tsplitpath_s(lpDir, lpDrive, 4, NULL, 0, lpFile, _MAX_FNAME, lpExt, _MAX_EXT);
lpDrive[2] = (TCHAR)'\\';
lpDrive[3] = (TCHAR)'\0';
int EventsNumber = 1;
DWORD Flags = FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_FILE_NAME;
hDir = CreateFile(lpDir, GENERIC_READ, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL);
if (hDir == INVALID_HANDLE_VALUE) {
DWORD err = GetLastError();
std::wcout << L"ERROR: CreateFile(folder to trace) function failed = " << err << std::endl;
return false;
///ExitProcess(err);
}
DWORD nBufferLength = 30000;
lpBuffer = malloc(nBufferLength);
BOOL bWatchSubtree = TRUE;
DWORD BytesReturned = 0;
HANDLE hEvent = CreateEvent(NULL, FALSE /*manual reset = true*/, FALSE /* initial state*/, NULL);
if (hEvent == NULL) {
printf("\n Cannot create event.\n");
CloseHandle(hDir);
return false;
//ExitProcess(GetLastError());
}
// =============================================================
OVERLAPPED Overlapped;
//---Overlapped.hEvent = hEvent;
LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine = cr;
// =============================================================
DoRDC = true;
while (_kbhit() == 0) {
if (DoRDC) {
ZeroMemory(&Overlapped, sizeof(Overlapped));
BOOL res_rdc = ReadDirectoryChangesW(hDir,
lpBuffer,
nBufferLength,
bWatchSubtree,
Flags,
&BytesReturned,
&Overlapped,
lpCompletionRoutine);
bool ok_rdc = (res_rdc != 0);
if (ok_rdc) {
}
else {
DWORD err = GetLastError();
std::wcout << L"ReadDirectoryChangesW error = " << err << std::endl;
}
DoRDC = false;
}
// Wait for notification.
//std::wcout << L"SleepEx" << std::endl;
SleepEx(1000, TRUE);
}
CloseHandle(hEvent);
CloseHandle(hDir);
free(lpBuffer);
}
I have implemented a program that traces changes in a given folder using ReadDirectoryChangesW
in overlapped mode with a completion routine. It works good.
I am planning to reconstruct it to make a more universal library.
When the completion routine cr
called, and file changes are displayed, I need to continue tracing: see line DoRDC = true; // RESTART WATCHING
.
It was possible in the current version, because it run in a loop while (_kbhit() == 0) {
, but after reconstruction I will eliminate this loop.
WatchDirectory
will call ReadDirectoryChangesW
at first only.
My question is: how should I restart the tracing inside cr
?
Will it be correct to call ReadDirectoryChangesW
inside the completion routine cr
?
But it may cause call of cr
when the previous call was not finished...
May be there is a way to tell ReadDirectoryChangesW
not to stop tracing ?
My code is below. The main function - WatchDirectory();
LPVOID lpBuffer = NULL;
bool DoRDC = true;
VOID WINAPI cr(DWORD dwErrorCode,
DWORD dwNumberOfBytesTransfered,
LPOVERLAPPED lpOverlapped) {
// Completion routine
DoRDC = true; // RESTART WATCHING
std::wcout << L" ------------- lpCompletionRoutine --------------- " << std::endl;
std::wcout << L" ErrCode = " << dwErrorCode
<< L" BytesTransferred = " << dwNumberOfBytesTransfered << std::endl;
if (dwErrorCode != 0) {
return;
}
std::wcout << L"..............." << std::endl;
// simply display dir changes
DisplayFileInfo(lpBuffer, dwNumberOfBytesTransfered);
}
bool WatchDirectory(LPTSTR lpDir)
{
// AFTER RECONSTRUCTION WILL CALL ReadDirectoryChangesW 1 TIME WITHOUT A LOOP
DWORD dwWaitStatus;
HANDLE dwChangeHandles[2];
TCHAR lpDrive[4];
TCHAR lpFile[_MAX_FNAME];
TCHAR lpExt[_MAX_EXT];
HANDLE hDir = INVALID_HANDLE_VALUE;
std::wcout << L"3_Watching for: " << lpDir << std::endl;
_tsplitpath_s(lpDir, lpDrive, 4, NULL, 0, lpFile, _MAX_FNAME, lpExt, _MAX_EXT);
lpDrive[2] = (TCHAR)'\\';
lpDrive[3] = (TCHAR)'\0';
int EventsNumber = 1;
DWORD Flags = FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_FILE_NAME;
hDir = CreateFile(lpDir, GENERIC_READ, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL);
if (hDir == INVALID_HANDLE_VALUE) {
DWORD err = GetLastError();
std::wcout << L"ERROR: CreateFile(folder to trace) function failed = " << err << std::endl;
return false;
///ExitProcess(err);
}
DWORD nBufferLength = 30000;
lpBuffer = malloc(nBufferLength);
BOOL bWatchSubtree = TRUE;
DWORD BytesReturned = 0;
HANDLE hEvent = CreateEvent(NULL, FALSE /*manual reset = true*/, FALSE /* initial state*/, NULL);
if (hEvent == NULL) {
printf("\n Cannot create event.\n");
CloseHandle(hDir);
return false;
//ExitProcess(GetLastError());
}
// =============================================================
OVERLAPPED Overlapped;
//---Overlapped.hEvent = hEvent;
LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine = cr;
// =============================================================
DoRDC = true;
while (_kbhit() == 0) {
if (DoRDC) {
ZeroMemory(&Overlapped, sizeof(Overlapped));
BOOL res_rdc = ReadDirectoryChangesW(hDir,
lpBuffer,
nBufferLength,
bWatchSubtree,
Flags,
&BytesReturned,
&Overlapped,
lpCompletionRoutine);
bool ok_rdc = (res_rdc != 0);
if (ok_rdc) {
}
else {
DWORD err = GetLastError();
std::wcout << L"ReadDirectoryChangesW error = " << err << std::endl;
}
DoRDC = false;
}
// Wait for notification.
//std::wcout << L"SleepEx" << std::endl;
SleepEx(1000, TRUE);
}
CloseHandle(hEvent);
CloseHandle(hDir);
free(lpBuffer);
}
Share
Improve this question
asked Nov 19, 2024 at 18:06
LUNLUN
1031 silver badge7 bronze badges
2
|
1 Answer
Reset to default 2how should I restart the tracing inside
cr
? Will it be correct to callReadDirectoryChangesW
inside the completion routinecr
?
Yes. You must call ReadDirectoryChangesW()
again every time a success completion is reported.
But it may cause call of
cr
when the previous call was not finished...
The completion routine is executed when the calling thread is in an alertable state. Since you are already inside of the routine, any new requests will be cached and the routine will be called again at a later time after the routine has exited and the calling thread has a chance to enter a new alertable state.
本文标签: cHow to continue read directory changes after 1st ReadDirectoryChangesW callStack Overflow
版权声明:本文标题:c++ - How to continue read directory changes after 1st ReadDirectoryChangesW call? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742407596a2469143.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
lpBuffer
global leaves you with non-reentrant functions, a nasty surprise for anyone writing multi-threaded code, and opens it up to abuse or accidental reuse by other functions anywhere in the program turning debugging into a nightmare. Don't do this to yourself. Better solutions will be a bit harder to write, but writing code almost always takes much less time than debugging code, so time you spend making code easier to debug is paid back almost immediately. – user4581301 Commented Nov 19, 2024 at 18:23