Лог измененных документов (программно или интерактивно)Внешняя компонента для журналирования сохраненных или вновь созданных документов.
Компонента проверена на 25 релизе 1С:Предприятие 7.7. | | Автор статьи: romix | Редакторы: Последняя редакция №13 от 20.10.06 | История URL: http://kb.mista.ru/article.php?id=380 | |
Ключевые слова: перехват, запись, изменение, документ, платформа, журнал, лог, МОД, УРБД
Файл для скачивания:
http://x-romix.narod.ru/vk_log_write_doc.rar
(Скачивать ЛЕВОЙ кнопкой мыши, ~72 килобайта)
Приложена работающая тестовая конфигурация.
Приложен исходный код (компилятор - Delphi 6).
Часто (например, при реализации обмена между информационными базами 1С/не 1С) требуется знать, какие объекты (например, документы 1С) пользователи (или не пользователи, а программисты) изменяли за промежуток времени.
Приведенная компонента перехватывает программное (док.Записать()) или интерактивное сохранение документов.
Также перехватываются действия:
- Создание новых документов
- Пометка на удаление
- Снятие пометки на удаление
- Проведение
- Отмена проведения
- Изменение времени документа
- Удаление помеченных объектов
- Включение и выключение проводок
Работающий образец использования внешней компоненты приведен в тестовой конфигурации (папка BASE_V77).
Для первого запуска компоненты требуются права администратора или привилегированного пользователя Windows.
Компонента протестирована только для 25 релиза 1С:Предприятие 7.7.
Под другими релизами использование не рекомендуется и работоспособность не гарантируется, поскольку внутреннее устройство платформы может (или могло) измениться.
Журнал имеет следующий вид:
----------
Объект={"O","0","0","0","0","0"," 12 62193782 "}
Действие=ЗаписьДокументаПрограммно
User=romix
Comp=ROMIX
Время=16.10.2006, 03:34:51
----------
Объект={"O","0","0","0","0","0"," 12 62193782 "}
Действие=Проведение
User=romix
Comp=ROMIX
Время=16.10.2006, 03:34:51
Извлечение объектов
Объект можно извлечь из журнала при помощи функции ЗначениеИзСтрокиВнутр().
Объект={"O","0","0","0","0","0"," 12 62193782 "}
Чтобы не блокировать действия пользователей, я использую метод
имяф=vk_log_write_doc.ПереименоватьЛогФайл();
(см. образец конфигурации в приложенном архиве).
Метод возвращает новое имя файла (в той же папке), и этот файл можно читать обычными средствами.
Чтобы избежать конфликтов при совместном доступе, я блокирую файл с расширением ".lck".
Последовательность действий в отладчике
Если кому-то будет интересно, опишу последовательность своих действий в отладчике (SoftICE).
Чтобы выявить, а какие же функции вызываются, я ставлю точку останова (команда BPX) на Kernel32!WriteFile, затем выполняю действие (например, записываю документ в 1С, удаляю документ и т.д.).
По срабатыванию брейкпойнта сразу же убраю (команда BD) эту точку (иначе она будет мешать).
Иду вверх (клавиша F12) по стеку вызовов функций.
При помощи этой несложной методики удалось выяснить, что за различные действия в 1С отвечают эти функции:
?WriteDocFromContext@@YAHPAVCDocSet@@PAVCOperSet@@HPAVCDocContext@@@Z
?WriteDocFromForm@@YAHPAVCDocSet@@PAVCOperSet@@HHPAVCDocTransacter@@PAVCValue@@H@Z
?MakePosting@CDocTransacter@@QAEHXZ
?MakeUnPosting@CDocTransacter@@QAEHXZ
?DeleteDocFromContext@@YAHPAVCDocSet@@PAVCOperSet@@H@Z
?DeleteDoc@@YAHPAVCDocSet@@J@Z
?ChangeTimeDoc@@YAHPAVCDocSet@@J@Z
?JustDeleteDoc@@YAHPAVCDocSet@@@Z
?OnOffProvs@COperSet@@QAEHH@Z
Параметры же этих функций найти несколько труднее: после некоторого (достаточно продолжительного) втыкания я выяснил, что описатель документа вида
03 B5 01 01 (ObjID)
00 20 20 20 (УРБД)
00 00 00 13 (тип)
передается через стек (первый параметр), ESI или ECX, и находится по смещению 158h (магическое значение).
Для ЗначениеВСтрокуВнутр() эти три 4-байтовых значения будут закодированы так:
{"O","0","0","0","0","0"," 19 62193921 "}
Нам интересно только последнее значение: " 19 62193921 ".
Оно состоит из следующих полей:
- Первые 10 байт - идентификатор типа (в десятичной форме)
- Вторые 10 байт - идентификатор объекта (в десятичной форме)
- Последние 3 байта - описатель базы УРБД (по умолчанию - 3 пробела).
Выявленные события я пишу в файл журнала (имя файла можно указать в настройках внешней компоненты).
|