Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / WINDOWS API: FindFirstChangeNotification() и WaitForSingleObject() не ловят изменение. / 5 сообщений из 5, страница 1 из 1
18.09.2013, 15:04
    #38400251
nrmBeginner
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WINDOWS API: FindFirstChangeNotification() и WaitForSingleObject() не ловят изменение.
Код использующий 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
18.09.2013, 16:11
    #38400398
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WINDOWS API: FindFirstChangeNotification() и WaitForSingleObject() не ловят изменение.
nrmBeginner,

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

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

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

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


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