powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / WINDOWS API: FindFirstChangeNotification() и WaitForSingleObject() не ловят изменение.
5 сообщений из 5, страница 1 из 1
WINDOWS API: FindFirstChangeNotification() и WaitForSingleObject() не ловят изменение.
    #38400251
nrmBeginner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код использующий WINDOWS API:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
int main(int argc, char* argv[])
{
	...
	watch( argv[1] )
	...
}

HANDLE notifyH; //Дескриптор слежения за изменениями в каталоге

bool watch(char* watchedDir)
{
	...
	notifyH = FindFirstChangeNotification(watchedDir, TRUE, FILE_NOTIFY_CHANGE_LAST_WRITE);
	...
	_watch();
	...
}


bool _watch(void)
{
	...
	while(true) {
		...
		WaitForSingleObject(notifyH, INFINITE)
		...
		FindNextChangeNotification(notifyH)
		...
	}
	return true;
}



Проблема в том что после вызова программы, первое изменение в наблюдаемом каталоге почему-то проходит незамеченым, это то изменение которое происходит после вызова FindFirstChangeNotification(), все же остальные изменения после вызова FindNextChangeNotification() ловятся успешно. Что я делаю не так?
GetLastError() ошибок не выдает.

P.S.
Да и кстати, вопрос модераторам, куда постить вопрос, если он относится чисто к операционной системе, а программисты сидят в разделах программирования?

Вот полный код если нужно:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
#include "windows.h"
#include <stdio.h>
#include <stdlib.h>
#include "stdbool.h"

//размер буфера для заполнения функцией ReadDirectoryCahgnesW()
#define BUF_ECNT (sizeof(FILE_NOTIFY_INFORMATION) + sizeof(WCHAR) * MAX_PATH)

bool watch(char* watchedDir);
bool _watch(void);

int main(int argc, char* argv[])
{
	//Аргументы:
	if(argc != 2) {
		printf("usage: %s {path}\n", argv[0]);
		return EXIT_FAILURE;
	}
	
	//Работа:
	if( !watch( argv[1] ) ) {
		return EXIT_FAILURE;
	}
	
	return EXIT_SUCCESS;
}

FILE_NOTIFY_INFORMATION* infoBuffer;
HANDLE notifyH; //Дескриптор слежения за изменениями в каталоге
HANDLE watchedDirH;

bool watch(char* watchedDir)
{
//Следит за каталогом watchedDir
//Bнициализирует слежение, вызывает _watch() для слежения, завершает слежение.
	
	bool returnValue = true;
	
	//Инициализация дескриптора слежения
	notifyH = FindFirstChangeNotification(watchedDir, TRUE, FILE_NOTIFY_CHANGE_LAST_WRITE);
	
	if( notifyH == INVALID_HANDLE_VALUE ) {
		fprintf(stderr, "ERROR: Can't watch %s.", watchedDir);
		return false;
	}
	
	//Размещение буффера для извлечения инфо. об изменениях в каталоге
	if( NULL == (
					infoBuffer =
					//(FILE_NOTIFY_INFORMATION*) calloc( BUF_ECNT, sizeof(FILE_NOTIFY_INFORMATION) )
					(FILE_NOTIFY_INFORMATION*) malloc( BUF_ECNT )
				)
		) {
		fputs("ERROR: Can't allocate heap.", stderr);
		returnValue = false;
		goto deleteHandle;
	}
	
	//Открытие наблюдаемого каталога
	watchedDirH = CreateFile(watchedDir,
					GENERIC_READ,
					FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
					NULL,
					OPEN_EXISTING,
					FILE_FLAG_BACKUP_SEMANTICS,
					NULL
				);
	if( watchedDirH == 0 || watchedDirH == INVALID_HANDLE_VALUE) {
		fputs("ERROR: Can't open watched directory.", stderr);
		returnValue = false;
		goto deleteBuffer;
	}
	
	
	_watch(); // Слежение.
	
	
	//Закрытие наблюдавшегося каталога
	if( 0 == CloseHandle(watchedDirH) ) {
		fputs("WARNING: Can't close watched directory.", stderr);
	}
	
	
	//Уничтожение буффера infoBuffer
	deleteBuffer:
	free(infoBuffer);
	
	deleteHandle:
	//Завершение слежения:
	if( !FindCloseChangeNotification( notifyH ) ) {
		fputs("WARNING: Can't close notification handler.", stderr);
		//return false;
	}
	
	
	return returnValue;
}
//--------------------------------------------------------

bool _watch(void)
{
//Непосредственно следит за каталогом на который указывает
//дескриптор слежения notifyH
	unsigned counter = 0; // Счетчик итераций.
	DWORD dwRetBufSize = 8; // Размер буфера который возвращает ReadDirectoryChangesW().
	char fileNameMsgBuf[MAX_PATH]; // Буфер имени файла в котором произошли изменения. Возращает ReadDirectoryChangesW()
	unsigned multiByteLen; //Длинна текстовой строки возвращенной фнкцией WideCharToMultiByte()
	
	puts("watch...");
	while(true) {
		//Ожидание изменения
		if( WaitForSingleObject(notifyH, INFINITE) == WAIT_FAILED ) {
			fputs("ERROR: Wait function fail.", stderr);
			return false;
		}
		
		//Чтение изменения
		if ( 0 == ReadDirectoryChangesW(
						watchedDirH,
						infoBuffer,
						BUF_ECNT /** sizeof(FILE_NOTIFY_INFORMATION)*/,
						TRUE /*subtree?*/,
						FILE_NOTIFY_CHANGE_LAST_WRITE,
						&dwRetBufSize,
						NULL, NULL
					)
			) {
			fputs("ERROR: Can't obtain change info.", stderr);
			return false;
		}
		
		printf("watch %u\n", ++counter);
		//printf("returned buffer size is %u (%f)\n", (unsigned)dwRetBufSize, (float)dwRetBufSize / sizeof(FILE_NOTIFY_INFORMATION) );
		if( 0 == (multiByteLen = WideCharToMultiByte(CP_OEMCP,
									0,
									infoBuffer->FileName,
									infoBuffer->FileNameLength / sizeof(WCHAR),
									fileNameMsgBuf,
									MAX_PATH,
									NULL,
									NULL
								) )
							) {
			fputs("ERROR: Obtained change info is incorrect.", stderr);
		} else {
			fileNameMsgBuf[multiByteLen] = 0;
			puts(fileNameMsgBuf);
		}
		
		//Перезаряжаем дескриптор изменений
		if ( 0 == FindNextChangeNotification(notifyH) ) {
			fputs("ERROR: FindNextChangeNotification() fail.", stderr);
			return false;
		}
	}
	return true;
}

...
Рейтинг: 0 / 0
WINDOWS API: FindFirstChangeNotification() и WaitForSingleObject() не ловят изменение.
    #38400398
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
nrmBeginner,

Посылай в "программирование", не ошибешься.
...
Рейтинг: 0 / 0
WINDOWS API: FindFirstChangeNotification() и WaitForSingleObject() не ловят изменение.
    #38401097
sherzod_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
nrmBeginner,

Приходилось разбираться с ожиданием изменений в каталоге. Не могу сейчас привести источник на мсдн, но помню что работал он очень ненадежно, и вроде как предназначен для простеньких задач, вроде обновления содержимого папки в проводнике. Какие-то критичные задачи вешать на него не стоит, я тогда сделал просто через скан директории через определенное время.
...
Рейтинг: 0 / 0
WINDOWS API: FindFirstChangeNotification() и WaitForSingleObject() не ловят изменение.
    #38401207
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sherzod_,

Здрасте, в explorer и far работают четко, поверено уже реально годами.

Оно по сети не работает, или не всегда работает, это я знаю. А в остальных случаях все очень надежно.
...
Рейтинг: 0 / 0
WINDOWS API: FindFirstChangeNotification() и WaitForSingleObject() не ловят изменение.
    #38401511
sherzod_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivsherzod_,
Здрасте, в explorer и far работают четко, поверено уже реально годами.
Оно по сети не работает, или не всегда работает, это я знаю. А в остальных случаях все очень надежно. Надежно можно понимать по разному. Для визуального наблюдения в фаре и в эксплорере это надежно, а когда в папку пишутся десятки файлов в секунду и нужно вешать обработчик на каждый новый файл - ненадежно (пропускаются события, группируются и тд).
...
Рейтинг: 0 / 0
5 сообщений из 5, страница 1 из 1
Форумы / C++ [игнор отключен] [закрыт для гостей] / WINDOWS API: FindFirstChangeNotification() и WaitForSingleObject() не ловят изменение.
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]