Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "WinAPI";
Текущий архив: 2004.10.24;
Скачать: [xml.tar.bz2];

Вниз

Проблема с 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 вся ветка

Форум: "WinAPI";
Текущий архив: 2004.10.24;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.48 MB
Время: 0.063 c
1-1097561774
aleshap
2004-10-12 10:16
2004.10.24
Как получить список свойств класса


8-1091010710
СтёпКин
2004-07-28 14:31
2004.10.24
Запись в JPG при видеозахвате


14-1096969651
karat
2004-10-05 13:47
2004.10.24
Здесь есть кто с Калининграда?


14-1096646698
asdqwer
2004-10-01 20:04
2004.10.24
Темы


14-1096719098
Piter
2004-10-02 16:11
2004.10.24
Как узнать размеры максимизированной формы?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский