Форум: "WinAPI";
Текущий архив: 2007.07.08;
Скачать: [xml.tar.bz2];
ВнизУзнать о закрытии handle Найти похожие ветки
← →
MetalFan © (2006-11-21 14:50) [0]есть такая программка, Unlocker.
она позволяет, на сколько я понимаю, закрывать окрытые другими процессами файлы...
как мне из своей программы узнать, что сторонняя программа взяла и закрыла хэндл открытого моей программой файла?
кроме периодических попыток обращения на чтение ничего в голову не приходит.
как можно "запретить" ей хозяйничать открытми в моем приложении
файлами?
з.ы. сайт программки http://ccollomb.free.fr/unlocker/index.htm
← →
Rouse_ © (2006-11-21 14:59) [1]Она работает через драйвер - с драйвером может поспорить только еще один драйвер, поэтому не запретишь. А по поводу реакции на момент разблокирования, лови изменения через ReadDirectoryChangesW
← →
MetalFan © (2006-11-21 16:36) [2]хм... надо поискать примеры...
← →
MetalFan © (2006-11-21 22:12) [3]а какое событие возникает в данном случае?
← →
Джо © (2006-11-21 22:16) [4]> [3] MetalFan © (21.11.06 22:12)
> а какое событие возникает в данном случае?
Никакого.
← →
BiN © (2006-11-21 22:21) [5]Для отслеживания закрытия хэндла файла можно пойти немного неуклюжим, но рабочим путем - WaitForSingleObject
← →
Rouse_ © (2006-11-21 22:24) [6]> какое событие возникает в данном случае?
Товарищь, вы находитесь в конференции АПИ, события - это часть модели ООП :) А вот нотификацию в калбеке можно поймать на FILE_NOTIFY_CHANGE_LAST_ACCESS
← →
MetalFan © (2006-11-22 12:27) [7]
> нотификацию в калбеке
сорри, именно так) не правильно выразился.
вот нашел несколько примеровunction ReadDirectoryChangesW(
hDirectory: THandle; // описатель каталога, за которым надо следить
lpBuffer: Pointer; // Указатель на буфер, в который будет записана информация
nBufferLength: DWORD; // Размер буфера
bWatchSubtree: Bool; // Следить ли за подкаталогами
dwNotifyFilter: DWORD; // Фильтр действий
lpBytesReturned: LPDWORD; // Сколько было записано в буфер
lpOverlapped: POverlapped; // Для асинхронной работы
lpCompletionRoutine: FARPROC // Функция, которая будет вызвана при окончании операции
): BOOL; stdcall;
procedure WorkThread(LV: TListView); stdcall;
procedure WorkThread(LV : TListView);stdcall;
var
hDir : THandle;
lpBuf : Pointer;
Ptr : Pointer;
cbReturn : Cardinal;
FileName : PWideChar;
Item : TListItem;
sTime : _SYSTEMTIME;
begin
// Сначала нам надо получить описатель каталога, за которым мы будем следить
// В данном примере это будет весь диск C:
hDir := CreateFile ("C:\",GENERIC_READ,FILE_SHARE_READ or FILE_SHARE_WRITE
or FILE_SHARE_DELETE,nil,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,0);
// Если ошиблись...
if hDir = INVALID_HANDLE_VALUE
then begin ShowMessage(SysErrorMessage(GetLastError)); exit; end;
// Выделяем память под буфер
// const BUF_SIZE = 2048 - думаю вполне достаточно
GetMem(lpBuf,BUF_SIZE);
repeat
// очищаем память перед записью в нее (на всякий случай)
ZeroMemory(lpBuf,BUF_SIZE);
// Теперь мы будем ждать пока чего-нибудь в интересующем нас каталоге
// изменится или произойдет ошибка (и мы выйдем из цикла)
// FILE_NOTIFY_CHANGE - это список флагов
if not ReadDirectoryChangesW(hDir,lpBuf,BUF_SIZE,true,
FILE_NOTIFY_CHANGE,@cbReturn,nil,nil)
then Break;
// Сюда мы попадаем, если функция выполнилась успешно
// и lpBuf указывает на одну или несколько структур FILE_NOTIFY_INFORMATION
Ptr:=lpBuf;
repeat
// Добавляем новый элемент в TListView (ViewStyle = vsReport )
Item := LV.Items.Add;
// Выделяем память под имя файла
GetMem(FileName,PFileNotifyInformation(Ptr).FileNameLength+2);
// Очищаем память - чтобы последним символом после копирования
// был бы #0 нуль
ZeroMemory(FileName,PFileNotifyInformation(Ptr).FileNameLength+2);
// WinAPI функция для копирования Unicode строки
lstrcpynW(FileName,PFileNotifyInformation(Ptr).FileName,
PFileNotifyInformation(Ptr).FileNameLength div 2+1);
// Имя файла у нас дается относительно папки
// т.е.если изменится файл C:\File\test.dat, то FileName
// будет равно File\test.dat
Item.Caption:="C:\"+FileName;
// Имя файла нам больше не нужно - очищаем память
FreeMem(FileName);
// Определяем тип произошедшего действия
case PFileNotifyInformation(Ptr).Action of
FILE_ACTION_ADDED : Item.SubItems.Add("Файл был создан");
FILE_ACTION_REMOVED : Item.SubItems.Add("Файл был удален");
FILE_ACTION_MODIFIED : Item.SubItems.Add("Файл был изменен");
FILE_ACTION_RENAMED_OLD_NAME :
Item.SubItems.Add("Файл был переименован и в имени файла - предыдущее имя");
FILE_ACTION_RENAMED_NEW_NAME :
Item.SubItems.Add("новое имя после переименования");
else Item.SubItems.Add("Произошло что-то странное");
end;
// Время, когда произошло событие
GetLocalTime(sTime);
with sTime do
Item.SubItems.Add(Format("%.2d:%.2d:%.2d",[wHour,wMinute,wSecond])); // 13:54:20
// Если эта запись не последняя (NextEntryOffset < > 0), то...
if PFileNotifyInformation(Ptr).NextEntryOffset=0
then Break
else begin
// ... добавляем строку в примечания (если интересно посмотреть смещение)
Item.SubItems.Add("Offset : "+
IntToStr(PFileNotifyInformation(Ptr).NextEntryOffset));
//Передвигаем указатель на NextEntryOffset байт вперед
Inc(Cardinal(Ptr),PFileNotifyInformation(Ptr).NextEntryOffset);
// Теперь Ptr указывает на следующую запись
end;
// Передвигать надо именно Ptr, а не lpBuf
until false;
until false;
// Очищаем память
FreeMem(lpBuf);
end;
procedure TForm1.Button1Click(Sender: TObject);
var
ThID : Cardinal;
begin
// hThread - THandle - глобальная переменная
// Создаем поток
// LV - TListView, WorkThread - функция выше
hThread:=CreateThread(nil,0,@WorkThread,LV,0,ThID);
// В случае неудачи выводим сообщение
if hThread=0 then ShowMessage(SysErrorMessage(GetLastError));
end
иvar
Dir : string = "C:\"; \\ имя каталога
SubDirs : boolean; \\ следить за подкаталогами ?
type
FILE_NOTIFY_INFORMATION = record
NextEntryOffset: DWORD;
Action: DWORD;
FileNameLength: DWORD;
FileName: array [0..0] of WCHAR;
end;
var
hDir : THandle;
Buf : pointer;
Returned, BufSize : dword;
adr : DWORD;
fni : ^FILE_NOTIFY_INFORMATION absolute adr;
s : string;
ws : WideString;
const
wcs = SizeOf(WideChar); // = 2
FILE_LIST_DIRECTORY = ($0001); // directory
begin
hDir := CreateFile(PChar(Dir),
FILE_LIST_DIRECTORY,
FILE_SHARE_READ or FILE_SHARE_DELETE,
nil,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
0);
if hDir = INVALID_HANDLE_VALUE then Exit;
BufSize := 16*1024*1024; // 16 mb
GetMem(Buf, BufSize);
repeat
if ReadDirectoryChangesW(hDir, Buf, BufSize, SubDirs,
FILE_NOTIFY_CHANGE_FILE_NAME or
FILE_NOTIFY_CHANGE_DIR_NAME or
FILE_NOTIFY_CHANGE_ATTRIBUTES or
FILE_NOTIFY_CHANGE_SIZE or
FILE_NOTIFY_CHANGE_LAST_WRITE or
FILE_NOTIFY_CHANGE_LAST_ACCESS or
FILE_NOTIFY_CHANGE_CREATION or
FILE_NOTIFY_CHANGE_SECURITY, @Returned, nil, nil) then
begin
Adr := Cardinal(Buf);
while Adr < (Cardinal(Buf) + Returned) do
begin
case fni^.Action of
FILE_ACTION_ADDED : s := "Added";
FILE_ACTION_REMOVED : s := "Removed";
FILE_ACTION_MODIFIED : s := "Modified";
FILE_ACTION_RENAMED_OLD_NAME : s := "Renamed from";
FILE_ACTION_RENAMED_NEW_NAME : s := "Renamed to";
else s := "0x" + IntToHex(fni^.Action, 8);
end;
SetLength(ws, fni^.FileNameLength div wcs);
Move(fni^.FileName, ws[1], fni^.FileNameLength);
ListBox1.Items.Add(s + " "" + ws + """);
Inc(adr, fni^.FileNameLength - wcs + SizeOf(fni^));
end;
end;
until False;
CloseHandle(hDir);
FreeMem(Buf);
end
первый не нравится, что лезут из потока к LV,
а второй вроде как "ловит" только одно "событие"
← →
prisoner849 © (2007-01-28 00:40) [8]кстати, фукнция ReadDirectoryChangesW "не работает" с сетевыми папками, если размер буфера > 64 kB
любопытно, что в справке Win32 Programmer"s Reference об этом не упоминается...
пришлось рыть MSDN ;)
← →
GrayFace © (2007-01-28 16:32) [9]prisoner849 © (28.01.07 0:40) [8]
любопытно, что в справке Win32 Programmer"s Reference об этом не упоминается...
Это далеко не единственное, о чем там не упоминается.
Страницы: 1 вся ветка
Форум: "WinAPI";
Текущий архив: 2007.07.08;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.044 c