Текущий архив: 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.47 MB
Время: 0.036 c