Skip to content

Commit 8619982

Browse files
committed
Added DirWatch
1 parent b832238 commit 8619982

File tree

2 files changed

+125
-0
lines changed

2 files changed

+125
-0
lines changed

DirWatch.cpp

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
//#define WIN32_LEAN_AND_MEAN
2+
#include <Windows.h>
3+
#include <tchar.h>
4+
5+
#include <cstdlib>
6+
#include <cstdio>
7+
#include <memory>
8+
9+
template <typename T, typename D>
10+
auto unique_resource(T* t, D&& d)
11+
{
12+
return std::unique_ptr<T, D>(t, std::forward<D>(d));
13+
}
14+
15+
inline const FILE_NOTIFY_INFORMATION* GetNext(const FILE_NOTIFY_INFORMATION* event)
16+
{
17+
return event->NextEntryOffset ? (FILE_NOTIFY_INFORMATION*)((BYTE*)event + event->NextEntryOffset) : nullptr;
18+
}
19+
20+
void OutputDirectoryChanges(HANDLE hDir, const BOOL bSubdir, const DWORD dwNotifyFilter)
21+
{
22+
BYTE change_buf[1024];
23+
DWORD bytes = 0;
24+
if (!ReadDirectoryChangesW(hDir, change_buf, ARRAYSIZE(change_buf) * sizeof(change_buf[0]), bSubdir, dwNotifyFilter, &bytes, nullptr, nullptr))
25+
{
26+
_ftprintf(stderr, _T("Error ReadDirectoryChanges: 0x%08X\n"), GetLastError());
27+
}
28+
else
29+
{
30+
SYSTEMTIME time;
31+
GetLocalTime(&time);
32+
_tprintf(_T("%02u/%02u/%04u %02u:%02u:%02u.%03u"),
33+
time.wDay, time.wMonth, time.wYear,
34+
time.wHour, time.wMinute, time.wSecond, time.wMilliseconds);
35+
36+
for (const FILE_NOTIFY_INFORMATION* event = (FILE_NOTIFY_INFORMATION*) change_buf; event != nullptr; event = GetNext(event))
37+
{
38+
const DWORD name_len = event->FileNameLength / sizeof(wchar_t);
39+
switch (event->Action)
40+
{
41+
case FILE_ACTION_ADDED: wprintf(L" Added: %.*s", name_len, event->FileName); break;
42+
case FILE_ACTION_REMOVED: wprintf(L" Removed: %.*s", name_len, event->FileName); break;
43+
case FILE_ACTION_MODIFIED: wprintf(L" Modified: %.*s", name_len, event->FileName); break;
44+
case FILE_ACTION_RENAMED_OLD_NAME: wprintf(L" Renamed from: %.*s", name_len, event->FileName); break;
45+
case FILE_ACTION_RENAMED_NEW_NAME: wprintf(L" to: %.*s", name_len, event->FileName); break;
46+
default: _tprintf(_T("Unknown action!")); break;
47+
}
48+
}
49+
_tprintf(_T("\n"));
50+
}
51+
}
52+
53+
int _tmain(const int argc, const LPCTSTR argv[])
54+
{
55+
LPCTSTR sDir = nullptr;
56+
BOOL bSubdir = FALSE;
57+
const DWORD dwNotifyFilter = FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE;
58+
for (int argi = 1; argi < argc; ++argi)
59+
{
60+
LPCTSTR arg = argv[argi];
61+
if (_tcsicmp(arg, _T("/s")) == 0)
62+
bSubdir = TRUE;
63+
else if (sDir == nullptr)
64+
sDir = arg;
65+
else
66+
_ftprintf(stderr, _T("Unknown argument: %s\n"), arg);
67+
}
68+
69+
if (sDir == nullptr)
70+
{
71+
_tprintf(_T("Usage: DirWatch [/s] <directory>\n"));
72+
return EXIT_SUCCESS;
73+
}
74+
75+
auto hDir = unique_resource(CreateFile(sDir,
76+
FILE_LIST_DIRECTORY,
77+
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
78+
NULL,
79+
OPEN_EXISTING,
80+
FILE_FLAG_BACKUP_SEMANTICS,
81+
NULL),
82+
[](HANDLE h) { CloseHandle(h); });
83+
if (!hDir)
84+
{
85+
_ftprintf(stderr, _T("Error CreateFile: 0x%08X\n"), GetLastError());
86+
return EXIT_FAILURE;
87+
}
88+
89+
#if 0
90+
auto hWatch = unique_resource(FindFirstChangeNotification(sDir, bSubdir, dwNotifyFilter), [](HANDLE h) { FindCloseChangeNotification(h); });
91+
if (!hWatch)
92+
{
93+
_ftprintf(stderr, _T("Error FindFirstChangeNotification: 0x%08X\n"), GetLastError());
94+
return EXIT_FAILURE;
95+
}
96+
97+
OutputDirectoryChanges(hDir.get(), bSubdir, dwNotifyFilter);
98+
99+
DWORD dwWait;
100+
while ((dwWait = WaitForSingleObject(hWatch.get(), INFINITE)) == WAIT_OBJECT_0)
101+
{
102+
if (FindNextChangeNotification(hWatch.get()) == FALSE)
103+
{
104+
_ftprintf(stderr, _T("Error FindNextChangeNotification: 0x%08X\n"), GetLastError());
105+
break;
106+
}
107+
108+
OutputDirectoryChanges(hDir.get(), bSubdir, dwNotifyFilter);
109+
}
110+
111+
if (dwWait != WAIT_OBJECT_0)
112+
{
113+
_ftprintf(stderr, _T("Error WaitForSingleObject: 0x%08X: 0x%08X\n"), dwWait, GetLastError());
114+
return EXIT_FAILURE;
115+
}
116+
#else
117+
while (true)
118+
OutputDirectoryChanges(hDir.get(), bSubdir, dwNotifyFilter);
119+
#endif
120+
121+
return EXIT_SUCCESS;
122+
}

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ Set the icon of the console window
3333
## [CreateGuid](CreateGuid.cpp)
3434
Create a guid.
3535

36+
## [DirWatch](DirWatch.cpp)
37+
Watch for changes in a direcory using [ReadDirectoryChanges](https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-readdirectorychangesw).
38+
3639
## [DragDrop](DragDrop.cpp)
3740
Simulates drag and dropping a file onto a window
3841

0 commit comments

Comments
 (0)