Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.10.24;
Скачать: CL | DM;

Вниз

Проблема с ReadDirectoryChangesW   Найти похожие ветки 

 
GrEG   (2004-09-20 20:07) [0]

Доброго всем времени суток.
Возникла необходимость написать простенький контролер изменений содержимого директории. FindFirstChangeNotification с последующим вызовом FindNextChangeNotification не подходит, так как нужно точно знать какие файлы были добавлены/удалены из папки. Решил воспользоваться ReadDirectoryChangesW в синхронном режиме, но сразу возникли две проблемы:
1) как прервать вызов функции?
2) при включеном контролере не удается переименовать файл в контролируемой директории.
С первой проблемой удалось кое-как разобраться, хотя и достаточно грубо: ReadDirectoryChangesW вызывается в отдельном потоке и, при необходимости, поток убивается через TerminateThread (с последующим освобождением ресурсов и Handle"ов).
Со второй проблемой справиться не удалось, MSDN также ситуацию не прояснил. Выяснил, что блокировка возможности переименования файлов происходит после получения Handle контролируемой директории:

hDir:=CreateFile(
 PChar(FPath),
 GENERIC_READ or GENERIC_WRITE,
 FILE_SHARE_READ or FILE_SHARE_DELETE,
 nil,
 OPEN_EXISTING,
 FILE_FLAG_BACKUP_SEMANTICS,
 0);

Вызов делаю в соответствии с рекомендациями Win32 help и MSDN.
Сталкивался ли кто-нибудь с подобной проблемой?


 
GrEG   (2004-09-20 20:09) [1]

Да, все проверялось на WinXP+SP1 и на Win2k+SP4. Поведение абсолютно идентично.


 
jack128 ©   (2004-09-20 22:22) [2]


> С первой проблемой удалось кое-как разобраться, хотя и
> достаточно грубо: ReadDirectoryChangesW вызывается в
> отдельном потоке и, при необходимости, поток убивается
> через TerminateThread (с последующим освобождением
> ресурсов и Handle"ов).

А может лудше в асинхронный режим перейти??


 
Fay ©   (2004-09-20 22:39) [3]

не лудше, а хыарашо.


 
jack128 ©   (2004-09-20 22:46) [4]

Fay ©   (20.09.04 22:39) [3]
хыарашо.

:-)) Мой диагноз - 2 литра пива :-))


 
XProger ©   (2004-09-21 02:06) [5]

А системные сообщения (BROADCAST) в винде такой информации не носят с собой?


 
Evgeny V ©   (2004-09-21 06:46) [6]

Лучше - это использовать асинхронный режим, OVERLAPPED

hDir := CreateFile(
 Pchar(DirName),                            
 FILE_LIST_DIRECTORY,  FILE_SHARE_READ or FILE_SHARE_DELETE or FILLE_SHARE_WRITE,
 nil,                                 OPEN_EXISTING ,                        FILE_FLAG_BACKUP_SEMANTICS or FILE_FLAG_OVERLAPPED,      0);

Тогда в потоке можно ждать сигнала об изменении в директории и например команды закрытия потока

MO.Offset:=0;
MO.OffsetHigh:=0;
MO.hEvent:=REvent;

ReadDirectoryChangesW(hDir,p,8192,false,FILE_NOTIFY_CHANGE_FILE_NAME  or
FILE_NOTIFY_CHANGE_LAST_WRITE ,@i,@MO,nil);

где MO -OVERLAPPED структура

Как вариант, создав еще Event в конструкторе потока, например CloseEvent, который устанавливаем в нашем деструкторе потока, общая идея кода будет примерно такой для Execute -  
// b - это array [0..1] of Thandle;

b[0]:=CloseEvent;// event закрытия потока
b[1]:=REvent;// event изменения диретории

MO.Offset:=0;
MO.OffsetHigh:=0;
MO.hEvent:=REvent;

hDir := CreateFile(
 Pchar(DirName),                            
 FILE_LIST_DIRECTORY,  FILE_SHARE_READ or FILE_SHARE_DELETE or FILLE_SHARE_WRITE,
 nil,                                 OPEN_EXISTING ,                        FILE_FLAG_BACKUP_SEMANTICS or FILE_FLAG_OVERLAPPED,      0);

ReadDirectoryChangesW(hDir,p,8192,false,FILE_NOTIFY_CHANGE_FILE_NAME  or
FILE_NOTIFY_CHANGE_LAST_WRITE ,@i,@MO,nil);
while not terminated do
begin
sig:=WaitForMultipleObjects(2,@b,false,INFINITE);
if sig = (WAIT_OBJECT_0) then // поток должен завершить работу
begin
ResetEvent(CloseEvent);
Terminate;
break;
end;

if sig = WAIT_OBJECT_0+1 then
begin
 ResetEvent(REvent);
// делаем что надо по сигналу изменения директории
......
// не забудем снова вызвать ReadDirectoryChangesW

ReadDirectoryChangesW(hDir,p,8192,false,FILE_NOTIFY_CHANGE_FILE_NAME or FILE_NOTIFY_CHANGE_DIR_NAME or
FILE_NOTIFY_CHANGE_LAST_WRITE ,@i,@MO,nil);
end;
end;// end While
// не забудем закрыть хэндл при выхоже из Execute,
if hDir <> INVALID_HANDLE_VALUE then
CloseHandle(hDir);


 
GrEG   (2004-09-21 08:00) [7]

Спасибо, попробую. Я не настаиваю, но ведь придется в любом случае вызывать CreateFile для получения Handle директории. А блокировка возможности переименования происходит именно после этого вызова, еще до первого вызова ReadDirectoryChangesW.


 
GrEG   (2004-09-21 08:44) [8]

Всем спасибо. Разобрался. Проблема с переименованием возникает из-за "неправильного" открытия директории. Если вызывать CreateFile c dwShareMode = FILE_SHARE_READ or FILE_SHARE_DELETE, то при попытке переименования файла возникает "Ошибка при совместном доступе к файлу". Если же dwShareMode = FILE_SHARE_READ or FILE_SHARE_DELETE or FILE_SHARE_WRITE, то все работает как и ожидалось - проблема исчезает: можно спокойно копировать, удалять, переименовывать файлы.
Что интересно, в хэлпе описан именно первый способ вызова.



Страницы: 1 вся ветка

Текущий архив: 2004.10.24;
Скачать: CL | DM;

Наверх




Память: 0.49 MB
Время: 0.138 c
4-1095880392
BKGG
2004-09-22 23:13
2004.10.24
Как узнать имя класса окна.


4-1095743160
Rem
2004-09-21 09:06
2004.10.24
Текст на панельки


14-1097047209
NewDelpher
2004-10-06 11:20
2004.10.24
Где бы скачать хороший учебник по UML с примерами?


4-1095875840
hgd
2004-09-22 21:57
2004.10.24
Как работать с WDM драйвером в delphi?


14-1096823961
Undert
2004-10-03 21:19
2004.10.24
Перехват системных событий в Windows