Отслеживание изменений каталога в REAL-TIME: Native ВК для 8.х

Давно у меня была задумка отследить, например, появление определенного файла в каталоге базы данных без использования различных таймеров и обработчиков ожидания. Настоящая ВК отслеживает изменения в выбранном каталоге в реальном времени и генерирует в 1С соответствующие внешние события. Выбранный каталог может быть как папкой, так и целым диском.

Настоящая ВК появилась как побочный продукт при выполнении проекта по отслеживанию «нежелательных» файлов на компьютерах корпоративной сети. Текущая версия позволяет поддерживать отслеживание изменений одновременно в двух папках (на двух дисках). Выполнена по технологии Native, не требует регистрации в реестре.

Подключение ВК:

ПодключитьВнешнююКомпоненту(ПолноеИмяФайлаВК,»DirSpy»,AddInType.Native);

Создание экземпляра класса:

Шпион = Новый(«AddIn.DirSpy.V8DirSpy»); // слева любая глобальная переменная.

ВНИМАНИЕ: не проводите никакие эксперименты по использованию локальной переменной класса (например, обработкой), получите дамп.

Методы ВК:

Каталог1(ИмяКаталога,фл_Добавлен,фл_Удален,фл_Модифицирован,фл_Переименован) — устанавливает отслеживание изменений в выбранном каталоге.

ИмяКаталога — строка

фл_Добавлен,фл_Удален,фл_Модифицирован,фл_Переименован — флаги генерации внешнего события, если Истина — генерируется событие:

Источник=»DIR_SPY»;

Событие- одно из:»FILE_ADDED»,»FILE_REMOVED»,»FILE_MODIFIED»,»FILE_RENAMED_OLD_NAME», «FILE_RENAMED_NEW_NAME».

Данные — полное имя файла.

Флажки — тип булево, необязательные, по умолчанию фл_Добавлен=Истина, остальные Ложь

Метод выполняется в отдельном потоке, возвращаемое значение — идентификатор потока. Если ноль — ошибка создания потока.

Каталог2(ИмяКаталога,фл_Добавлен,фл_Удален,фл_Модифицирован,фл_Переименован) — полностью идентичен методу Каталог1

ОтключитьПоток(ИдентификаторПотока) — отключает слежение и удаляет поток с указанным идентификатором

//--- модуль обычного приложения---
Перем Шпион Экспорт;
Функция КаталогИБ() Экспорт
КаталогИБ = СтрокаСоединенияИнформационнойБазы();
КаталогИБ = Сред(КаталогИБ,7,СтрДлина(КаталогИБ)-8) + "";
Возврат КаталогИБ;
КонецФункции
Процедура ПриНачалеРаботыСистемы()
ФайлВК=КаталогИБ()+"DirSpy.dll";
Файл= Новый Файл(ФайлВК);
Если Файл.Существует() Тогда
//-- подключение компоненты--
ПодключитьВнешнююКомпоненту(ФайлВК,"DirSpy",AddInType.Native);
//-- создание экземпляра класса--
Шпион =    Новый("AddIn.DirSpy.V8DirSpy");
Каталог="c:";   // весь диск С
//                            ADD     DEL  CHANGE RENAME
Хендл1=Шпион.Каталог1(Каталог,Истина,Истина,Ложь,Ложь);
Если Хендл1=0 Тогда
Сообщить("Не удалось создать поток");
КонецЕсли;

Каталог="d:";  // весь диск D
//                            ADD     DEL  CHANGE RENAME
Хендл2=Шпион.Каталог2(Каталог,Истина,Истина,Истина,Истина);
Если Хендл2=0 Тогда
Сообщить("Не удалось создать поток");
КонецЕсли;

Иначе
Сообщить("Не обнаружен файл ВК, скопируйте ""DirSpy.dll"" в КаталогИБ "
+ФайлВК,СтатусСообщения.Информация);
КонецЕсли;
КонецПроцедуры

Процедура ОбработкаВнешнегоСобытия(Источник, Событие, Данные)
Если Источник="DIR_SPY" Тогда
Сообщить("Событие: "+Событие+"; Данные: "+Данные);
КонецЕсли;
КонецПроцедуры

Примечание для продвинуто-любопытных: используется API ReadDirectoryChangesW

В архиве находится папка с тестовой базой+DirSpy.dll

37 Comments

  1. Alex1Cnic

    Интересно, а для 1С-ки как применить? а так плюс конечно за труды

    Reply
  2. Abadonna

    (1) Alex1Cnic,

    а для 1С-ки как применить?

    Самое первое, что приходит в голову:

    Процедура ОбработкаВнешнегоСобытия(Источник, Событие, Данные)
    Если Источник=»DIR_SPY» Тогда
    Если Событие=»FILE_ADDED» Тогда
    ИмяФайла=Данные;
    Если Найти(ИмяФайла,»GoNah»)>0 Тогда
    ЗавершитьРаботуСистемы(Ложь,Ложь);
    КонецЕсли;
    КонецЕсли;
    КонецЕсли;
    КонецПроцедуры
    
    

    Показать

    Reply
  3. Abadonna

    Да ВЕЗДЕ мои работают 😉 Эту конкретно не проверял

    Reply
  4. Ёпрст

    Прикольно..

    Reply
  5. Ёпрст

    Это… файло_ренайм пасёт ? Ну или просто изменение файла, атрибутов там его ?..

    Reply
  6. Abadonna

    (6) Ёпрст, это… а почитать не катит? 😉

    Reply
  7. Ёпрст

    Ээ.. че почитать ?

    На картинке вижу токма аддед и ремувед..

    Reply
  8. Ёпрст

    аа… вижу ненэйм..

    Ну молоток.

    Reply
  9. Abadonna

    (8)

    Ээ.. че почитать ?

    Подозреваю, что описание :)))

    Каталог1(ИмяКаталога,фл_Добавлен,фл_Удален,фл_Модифицирован,фл_Переименован) — устанавливает отслеживание изменений в выбранном каталоге.

    ИмяКаталога — строка

    фл_Добавлен,фл_Удален,фл_Модифицирован,фл_Переименован — флаги генерации внешнего события, если Истина — генерируется событие:

    Источник=»DIR_SPY»;

    Событие- одно из:»FILE_ADDED»,»FILE_REMOVED»,»FILE_MODIFIED»,»FILE_RENAMED_OLD_NAME«, «FILE_RENAMED_NEW_NAME«.

    На картинке:

    Reply
  10. Ёпрст

    (10) ага, вижу-вижу.

    Reply
  11. mptt

    Плюс одназначно.. Еще бы на исходники DirSpy взглянуть..

    Reply
  12. hogik

    Аркадий.

    Извини, не в тему напишу.

    Нажимаю звёздочку. Вхожу в список «одобряющих». Я в списке есть. Возвращаюсь на страницу разработки. Нажимаю звёздочку. Смотрю список — меня там нетУ. И так многократно можно повторить…

    Reply
  13. Abadonna

    (13)

    Не дай Бог жить с эпоху перестройки сайтов. (с) Древняя мудрость

    Фиг его знает, я три раза попробовал — три раза тебя в списке вижу

    Reply
  14. hogik

    (14)

    Дык. 😉 Я же плюс тебе ставлю нажатием звёздочки, а ты просто на меня смотришь.

    Т.е. если я тебе ставлю плюс настойчиво (многократным нажатием), то я его могу в результате и не поставить. Блеск… 🙁

    P.S.

    Написал ещё в теме про новый «дизайн» сайта. Может разберутся…

    Reply
  15. Abadonna

    (3) Eugeneer,

    Работает на управляемых формах? в клиент-сервере.

    Не поленился проверить на базе «Работа с клиентами», построенной на основе БП 3.0. Уэфнее и сервер-клиентнее не бывает:))

    &НаКлиенте
    Процедура ЗапуститьШпиона(Команда)
    Если Шпион=Неопределено Тогда  // Шпион — ГЛОБАЛЬНАЯ!
    Возврат;
    КонецЕсли;
    
    Каталог=»c:»;   // весь диск С
    Хендл1=Шпион.Каталог1(Каталог,Истина,Истина,Ложь,Ложь);
    Если Хендл1=0 Тогда
    Сообщить(«Не удалось создать поток»);
    КонецЕсли;
    КонецПроцедуры
    
    &НаКлиенте
    Процедура ВнешнееСобытие(Источник, Событие, Данные)
    Если Источник=»DIR_SPY» Тогда
    Сообщить(«Событие: «+Событие+»; Данные: «+Данные);
    КонецЕсли;
    КонецПроцедуры
    
    

    Показать

    Reply
  16. kirillkr

    (0) А для параноиков исходник библиотеки идет?

    Reply
  17. Abadonna

    (17) kirillkr,

    А для параноиков исходник библиотеки идет?

    Параноикам могу порекомендовать погуглить строчку «ReadDirectoryChangesW Дельфи», например 😉

    Reply
  18. kirillkr

    (18) и писать свою ВК? Зачем? Или там все-таки есть секретная отправка данных в АНБ?

    Reply
  19. Abadonna

    (19) kirillkr, я на ГРУ работаю 😉

    Прошли те времена, когда я исходники дарил.

    Reply
  20. kirillkr

    (20) вот так вот «Большой Брат» следит в России.

    Reply
  21. slimper
  22. Abadonna

    (22) slimper, is evil for crooked-hands arseholes

    Reply
  23. Evil Beaver

    Вещь полезная, API простой, всегда можно сделать при желании, но когда есть готовый вариант, лучше его использовать. Посему, исходники для параноиков все-таки не помешают. Но хозяин-барин, разумеется 🙂

    Reply
  24. Abadonna

    (24) Evil Beaver,

    API простой

    Ну, именно эту API я бы никак к простой не отнес, это не какой-нибудь FindWindow.

    но когда есть готовый вариант, лучше его использовать.

    Вот он, лежит готовый вариант — используйте :)))

    Reply
  25. Evil Beaver

    (25) дык, спасибо, как понадобится, так воспользуюсь. Но мой внутренний параноик хнычет:)

    Reply
  26. vladon

    Если не секрет, как в Native API генерировать внешние события?

    Reply
  27. Abadonna

    (27) vladon, см.ВК Native API

    type
    TV8AddInDefBase = class //IAddInDefBase см. документацию от 1С
    public
    procedure Destroy1; virtual; abstract;
    function AddError(wcode: word; const source: PWideChar;
    const descr: PWideChar;
    scode: integer): boolean; virtual; stdcall; abstract;
    function Read(wszPropName: PWideChar;
    pVal: PV8Variant;
    pErrCode: PInteger;
    errDescriptor: PPWideChar): boolean; virtual; stdcall; abstract;
    function Write(wszPropName: PWideChar;
    pVar: PV8Variant): boolean; virtual; stdcall; abstract;
    function RegisterProfileAs(wszProfileName: PWideChar): boolean; virtual; stdcall; abstract;
    function SetEventBufferDepth(lDepth: integer): boolean; virtual; stdcall; abstract;
    function GetEventBufferDepth: integer; virtual; stdcall; abstract;
    function ExternalEvent(wszSource, wszMessage, wszData: PWideChar): boolean; virtual; stdcall; abstract;
    procedure CleanEventBuffer; virtual; stdcall; abstract;
    function SetStatusLine(wszStatusLine: PWideChar): boolean; virtual; stdcall; abstract;
    procedure ResetStatusLine; virtual; stdcall; abstract;
    end;
    

    Показать

    Reply
  28. kentavr27

    Хотелось бы уточнить… Один экземпляр класса одновременно может отслеживать не более двух каталогов? Потому как при попытке второй раз использовать метод Хендл1=Шпион.Каталог1(Каталог,Истина,Истина,Ложь,Ложь) 1с-ка молча валится. Так и должно быть?

    Reply
  29. Abadonna

    (29) kentavr27, Мне даже в голову не приходило проверить на повторное использование, ибо — а на фиг?

    Проверил, да — валится. Пока считай, что так и должно быть. Посмотрю…

    Подправил, вот аж так теперь работает:

    Хендл1=Шпион.Каталог1(Каталог,Истина,Истина,Ложь,Ложь);
    Если Хендл1=0 Тогда
    Сообщить(«Не удалось создать поток»);
    КонецЕсли;
    Хендл1=Шпион.Каталог1(Каталог,Истина,Истина,Ложь,Ложь);
    Если Хендл1=0 Тогда
    Сообщить(«Не удалось создать поток»);
    КонецЕсли;
    Хендл1=Шпион.Каталог1(Каталог,Истина,Истина,Ложь,Ложь);
    Если Хендл1=0 Тогда
    Сообщить(«Не удалось создать поток»);
    КонецЕсли;
    Хендл1=Шпион.Каталог1(Каталог,Истина,Истина,Ложь,Ложь);
    Если Хендл1=0 Тогда
    Сообщить(«Не удалось создать поток»);
    КонецЕсли;
    
    

    Показать

    Будет новая, очень расширенная версия, там будет без косяка

    Reply
  30. Abadonna

    (29) Залил подправленную 1.0.0.2

    Reply
  31. Kalam

    А зачем это к 1С цеплять?

    А если в 1С, то почему не сделать через ОбработчикОжидания?

    В чем сила, брат?

    Reply
  32. Abadonna

    (32) Kalam,

    то почему не сделать через ОбработчикОжидания?

    Кто не дает? Делай. А мне надо было секунда в секунду — я для себя и сделал. А вот зачем мне это надо было — я сам знаю 😉

    И вообще у меня привычка дурная: чем через задницу в 1С выеживаться, мне проще ВК написать

    Reply
  33. Свой

    в 1С 7.7 компонента будет работать ?

    Reply
  34. Abadonna

    (34) Свой, нет, конечно. Native для 7.7 не предусмотрен. Кстати, еще один резон завязать с 7.7 😉

    Reply
  35. script

    Бeдет ли отслеживать компонента изменения файлов в ситевом каталоге или виртуальном, подключенном через RDP ?

    Reply
  36. Al777

    Заметил следующее. Платформа 8.2. Конфигурация: Комплексная автоматизация 1.1.76 + CRM 1.4.10. Подключение ВК производится при начале работы системы. Она хорошо работает, претензий нет, но пользователь, допустим, вынес какие-то отчёты в виде картинок или картинок с надписью на свою панель различных значков и закрыл 1С Предприятие. Когда опять открыл 1С Предприятие, то там нет последних сохранённых отчётов в виде картинок. Без использования этой ВК всё замечательно сохраняется и не слетает. Кто-нибудь с этим сталкивался? Как решили проблему?

    Reply
  37. Alias

    Событие «FILE_RENAMED_NEW_NAME» не приходит, есть только «FILE_RENAMED_OLD_NAME».

    Почему так может быть? С added, removed, modified проблем нет.

    Win 7 pro х64; 1С 8.3.10.

    P.S. к сожалению, понимаю, что вопрос не к автору ВК… 🙁 может у кого-то есть мысли или другая аналогичная ВК.

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *