Фоновое отслеживание изменений в файловой системеСтатья содержит пример внешней компоненты (компилятор - Delphi 6) с реализацией потоков (threads) и фонового отслеживания изменений в папке (каталоге) на диске. При этом используется системная функция API FindFirstChangeNotification, а не опрос директории через равные промежутки времени. | | Автор статьи: Последняя редакция №1 от 09.03.06 URL: http://kb.mista.ru/article.php?id=119 | |
Ключевые слова: Внешняя компонента, Delphi, поток, thread, TThread, опрос директории, отслеживание изменений в файлах, FindFirstChangeNotification, WaitForSingleObject
Отслеживание изменений в директории
При реализации обмена между программами часто требуется проинформировать принимающую программу (в нашем случае, 1С:Предприятие) о том, что файлы пришли, и их пора принимать.
Мы можем сканировать папку в процедуре обработки ожидания (например, делать это каждые N секунд).
Другой, пожалуй, более правильный способ - использовать системные функции FindFirstChangeNotification, FindNextChangeNotification и FindCloseChangeNotification из Windows API (аналогичные функции есть и в ОС Unix). В данном случае, оповещения об изменении в файловой системе выполняет ядро ОС.
Что мы делаем из кода 1С
///////////////////////////////////////////////////////////////////////
Процедура ПриНачалеРаботыСистемы() //Предопределенная процедура 1С
ЗагрузитьВнешнююКомпоненту(vk_ChangeNotification.dll)
vk=СоздатьОбъект("AddIn.vk_ChangeNotification");
vk.ОтслеживатьПодкаталоги=0;
vk.НачатьКонтрольИзменений("c:\");
КонецПроцедуры
После такой инициализации в процедуру ОбработкаВнешнегоСобытия 1С будет приходить оповещения об изменении, в данном примере, папки "c:\". Если установить параметр vk.ОтслеживатьПодкаталоги=1, то еще и вложенных папок. Отслеживаться будут только изменения в именах файлов (например, появление нового файла в директории), но не изменение содержания файлов.
///////////////////////////////////////////////////////////////////////
Процедура ОбработкаВнешнегоСобытия(Источник,Событие,Данные)//Предопределенная процедура 1С
//Глобальный обработчик внешнего события
Сообщить("Внешнее событие: Источник="+Источник+" Событие="+Событие+" Данные="+Данные);
КонецПроцедуры
Чтобы прекратить опрос, доступна функция
///////////////////////////////////////////////////////////////////////
Процедура ПриЗавершенииРаботыСистемы()
vk.ЗакончитьКонтрольИзменений();
КонецПроцедуры // ПриЗавершенииРаботыСистемы
Процедура потока в Delphi
//Процедура потока
procedure TMyThread.Execute;
var r: Cardinal;
var fn : THandle;
begin
fn:=0;
try
fn := FindFirstChangeNotification(pChar(MyObject.DirName), MyObject.CheckSubfolders, FILE_NOTIFY_CHANGE_FILE_NAME);
if fn=INVALID_HANDLE_VALUE then
RaiseLastOSError;
repeat
r := WaitForSingleObject(fn,2000);
if r = WAIT_OBJECT_0 then
MyObject.iEvent.ExternalEvent(c_AddinName, 'FolderChange', MyObject.DirName);
if not FindNextChangeNotification(fn) then begin
RaiseLastOSError;
break;
end;
until Terminated;
FindCloseChangeNotification(fn);
except
on E:Exception do begin
try
FindCloseChangeNotification(fn);
except
end;
MyObject.ShowErrorLog('Ошибка контроля папки: '+E.Message);
end;
end;
end;
Процедура генерирует события (ExternalEvent), как только обнаружит изменения в указанной папке файловой системы. Параметр FILE_NOTIFY_CHANGE_FILE_NAME указывает на необходимость контролировать имена файлов. См. справку по WinAPI (например, на диске MSDN), чтобы узнать, какие варианты этого параметра есть еще.
Внешняя компонента с исходным кодом и тестовой конфигурацией:
http://x-romix.narod.ru/vk_ChangeNotification.rar
(скачивать ЛЕВОЙ кнопкой мыши, 97 килобайт). |