Помощь - Поиск - Пользователи - Календарь
Полная версия: Перехватить переименование файла
Форум «Всё о Паскале» > Современный Паскаль и другие языки > Делфи
Unconnected
Привет всем.

Допустим, есть файл или папка, путь и имя известны. Нужно отловить событие переименования этого файла или папки и получить новое имя. Такое возможно?
volvo
Можно. С помощью функции MSDN -> ReadDirectoryChangesW, например.

Вот тут есть пример использования. Но он не совсем корректен, потому что вот так smile.gif
Unconnected
Я немного изменил процедуру (убрал ненужные фильтры), получилось так:

type
PFileNotifyInformation = ^TFileNotifyInformation;
TFileNotifyInformation = record
NextEntryOffset: DWORD;
Action: DWORD;
FileNameLength: DWORD;
FileName: array [0..MAX_PATH - 1] of WideChar;
end;

var writepath:string;//нужное мне имя папки

Procedure monitor1(direc:string);
const
Filter = FILE_NOTIFY_CHANGE_FILE_NAME or
FILE_NOTIFY_CHANGE_DIR_NAME or
FILE_NOTIFY_CHANGE_CREATION or
FILE_NOTIFY_CHANGE_SECURITY;
var
Dir: THandle;
Notify: TFileNotifyInformation;
BytesReturned: DWORD;
newname:string;
begin
Dir := CreateFile(pchar(direc), GENERIC_READ,
FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE,
nil, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
if Dir <> INVALID_HANDLE_VALUE then
try
if not ReadDirectoryChangesW(Dir, @Notify, SizeOf(TFileNotifyInformation),
False, Filter, @BytesReturned, nil, nil) then
raise Exception.Create(SysErrorMessage(GetLastError))
else
case Notify.Action of
FILE_ACTION_RENAMED_NEW_NAME: newname:=notify.FileName;
end;
renamefile(newname,writepath);
finally
CloseHandle(Dir);
end;
end;
...
begin
monitor(writepath);
end.



, оставил те, которые не знаю, зачем нужны) В процедуру передаю путь к папке, имя которой надо мониторить. Кстати, в msdn написано: The function does not report changes to the specified directory itself. Это случаем не значит, что программа не будет смотреть изменения папки, в которой сама находится? (да, знаю, что в большинстве случаев переименовать папку с работающей программой внутри не получится).
Так вот, запускаю её единожды - программа виснет. В таймере если запускать, тоже виснет. Как надо?

Добавлено через 15 мин.
Цитата
Это случаем не значит, что программа не будет смотреть изменения папки, в которой сама находится?


Даа, кажется именно это и значит..
volvo
Цитата
Так вот, запускаю её единожды - программа виснет
Что значит "виснет"? У тебя синхронный вызов, пока событие, которое программа должна отловить, не произойдет, программа дальше не двинется. Сделай асинхронный - не будет зависать. В MSDN написано, что надо для этого сделать...
volvo
Пример использования ReadDirectoryChangesW в отдельном потоке:
Unconnected
У меня D2007 этот проект не открыла, говорит, там файла какого-то не хватает. Я аккуратно перенёс всё в новый проект, вписал нужный путь (такой файл существует), при нажатии "Начать" ошибка "файл не найден" не выдаётся, но и слежения, как я понял, не происходит (в Memo не появляются записи о переименовании, удалении и т.п.). Прикладываю на всякий случай мой проект, хотя там всё то же самое.

volvo
Цитата
говорит, там файла какого-то не хватает
Какого именно, можешь уточнить? Я делал под D2009, там работает. Твой код тоже отрабатывает:
Нажмите для просмотра прикрепленного файла


Добавлено через 2 мин.
P.S. Какая ОС, уточни, кстати. Может это опять Вистовские заморочки? И еще одно: что у тебя возвращает ReadDirectoryChangesW? Если False, то проверь причину:
    if not ReadDirectoryChangesW(hDir, lpBuf, BUFFER, true, Filter, @cbReturn, nil, nil) then
begin
ShowMessage(SysErrorMessage(GetLastError)); // Вот так
Break;
end;
Unconnected
У меня Windows 7 Home Basic. Пробовал запускать свой проект на виртуалке с XP - при нажатии кнопки Начать выпрыгивает ошибка Windows (Отправить отчёт\не отправлять). Если открываю твой проект, то "Unable to load project C:\Users\Unconnected\Desktop\Spy Dir\Project1.dproj".

А ReadDirectoryChangeW возвращает False и выдаёт Error "Параметр задан неверно". На Севене я не под администратором сижу, запись в корень диска C: запрещена, например.
volvo
Цитата
На Севене я не под администратором сижу, запись в корень диска C: запрещена, например.
Так я и под XP не под администратором, если что, запись в корень диска у меня тоже запрещена, я ж в корень-то и не пишу, я в подпапку, а туда уже можно... Сейчас гляну, что там может вызывать такую ошибку.
volvo
Ты будешь смеяться, но:
Нажмите для просмотра прикрепленного файла

(Win7 Ultimate, запускал под НЕадминским аккаунтом).
Unconnected
Фигня какая-то.. И как я его уже только не пробовал) Volvo, а ты не мог бы ради интереса приложить скомпилированный exe, который у тебя работает? (да-да, я понимаю риск... smile.gif ))
volvo
Ну, понимаешь - тогда пробуй:
Unconnected
Создал C:\1\555_21.png - работает.. Наверное, руки не оттуда мои, попробую со средой поколдовать. Спасибо за код smile.gif
Unconnected
Поставил D2009, скомпилировал начальные исходники volvo - такая же фигня, только почему-то когда в CheckPath пишешь путь к папке - говорит про неверный параметр, а когда к файлу - не говорит ничего, но и не следит. Ладно, чёрт с ним, наверное, у меня в системе что-то наворочено. А можно тогда просто запретить переименование файла? Мне кажется, в сторону SetWindowsHookEx смотреть надо, там вроде любое действие отловить можно.

Добавлено через 17 мин.
И сам нагуглил-додумался smile.gif Достаточно открыть файл в потоке, TFileStream.
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.