Перехват методов серверных (x64) контекстов с использованием DynamicWrapperX

23.03.17

Разработка - Инструментарий разработчика

Применение COM-объекта DynamicWrapperX на x64-сервере приложений.

Файлы

ВНИМАНИЕ: Файлы из Базы знаний - это исходный код разработки. Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы. Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных. Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.

Наименование Скачано Купить файл
Тестовая база
.dt 59,82Kb ver:1.0
12 2 500 руб. Купить

Подписка PRO — скачивайте любые файлы со скидкой до 85% из Базы знаний

Оформите подписку на компанию для решения рабочих задач

Оформить подписку и скачать решение со скидкой

Вы можете заказать платную доработку или адаптацию этой разработки под вашу конфигурацию на «Бирже заказов».

  • 0% комиссии — оплата напрямую исполнителю;
  • Исполнители любого масштаба — от отдельных специалистов до команд под проект;
  • Прямой обмен контактами между заказчиком и исполнителем;
  • Безопасная сделка — при необходимости;
  • Рейтинги, кейсы и прозрачная система откликов.

Коллеги, хочу предложить Вам небольшое исследование на предмет изменения функционала серверных контекстов. Речь пойдет о x64-версии 1С сервера приложений для ОС Windows.

Несколько слов о терминах.

    Наверное, я не ошибусь, если скажу, что большинство объектов(в широком смысле этого слова), которые мы привыкли использовать на внутреннем языке платформы, в реальности представляют собой COM-объекты. Именно ими оперирует система. Такие объекты, как <Справочники>, <РезультатЗапроса>, <ДокументОбъект> и т.д, суть COM-объекты внутри движка. Даже числа и строки "оборачиваются" в COM-интерфейсы.

    В данном изложении я буду использовать термин Контекст, подразумевая под ним набор интерфейсов подобных Com-объектов. Описание самих интерфейсов и их IID вы вряд ли найдете в MSDN и regedit'ом в реестре, поскольку это сугубо внутренние интерфейсы платформы. Я не говорю сейчас об IUnknown, IDispatch и прочих стандартных интерфейсах. Среди набора интерфейсов 'внутренних' COM-объектов нам будет интересен интерфейс "вызова через <.>". Мне он видится как некий аналог IDispatch. Я буду ссылаться на него как IContextExtImpBase.

    Когда мы пишем, например, Справочники.<...>, именно в этот момент происходит обращение к методам интерфейса IContextExtImpBase. Хотя нет, если посмотреть на это более детально, то окажется, что объект 'Справочники', это свойство одного из глобальных контекстов (которых в 1С порядка 33), т.е. внутри обращение к 'Справочники' выглядит так <ГК(i)>.Справочники...И каждый из ГК поддерживает тот же IContextExtImpBase.

    Как известно, любой COM-интерфейс имеет строго определенную последовательность методов в виртуальной таблице, поэтому можно попытаться выполнить подмену какого-либо методов интерфейса. Например, за вызовы методов 1С-объектов отвечает метод "IContextExtImpBase::call". Если его подменить на что-то своё, то все вызовы методов 1С-го объекта будут проходить через ваш метод. Причем, это коснется всего серверного рабочего процесса.

    Моя цель была, попытаться минимальными усилиями, после перехвата, "всплыть" на уровень модуля 1С и уже тут продолжить обработку. Для экспериментов я использовал объект Запрос, как наиболее интересный в плане изменения функционала.Перехватывая его методы, можно, например, собирать статистику, ну или налету подменять текст запроса.(Не могу с уверенностью утверждать, но даже если конфигурация поставляется без текста модулей, текст запроса можно получить.)

Вариант реализации.

    Я применил не совсем стандартный подход для решения данной задачи, каюсь. Основные инструменты, которые я использовал, это COM-объект DynamicWrapperX и кусок бинарного кода. (Исходник есть в тестовой базе. Я старался делать подробные комментарии.). Оба написаны на goAsm'е. Весь остальной код написан на стандартном языке 1С. Уверен, что существуют более изящные варианты реализации, но, в любом случае, это всего лишь пример того, как это можно сделать.

Теперь предлагаю посмотреть, что есть в тестовой конфигурации, и рассмотреть, как работает перехват.

  • Серверный общий модуль 'DWX_Информатор'. Тут находятся служебные процедуры и функции для доступа к методам интерфейса IContextExtImpBase. Вообще говоря, сам модуль может использоваться независимо от данной разработки, но отдельно представляет скорее теоретический интерес. Возможно, его можно применить для UNIT-тестирования.
  • Служебная обработка 'Перехват', которая забрасывает кусок бинарного кода на сервер и устанавливает/снимает перехват.
  • Служебная обработка '_proxyInterceptor'. Основная обработка, в которой происходят перенаправления вызовов. Именно сюда (в модуль обработки) "всплывает" перехваченный вызов.
  • Обработка 'ОбработчикПерехвата'. Содержит пользовательские обработчики методов перехваченного контекста.

                Вот один из вариантов, как мог бы выглядеть перехваченный метод Запроса 'Выполнить': 

	Функция Событие_Запрос_Выполнить(Запрос) Экспорт 
		Сообщение 		= Новый СообщениеПользователю;
		Сообщение.Текст = "" + Запрос.Текст;
		Сообщение.Сообщить();	
		
		Рез = Перехватчик.ВыполнитьОригинальноеСобытие();
		
		Колво 			= ?(Рез = Неопределено, 0, Рез.Выбрать().Количество());
		Сообщение.Текст = "Размер выборки:" + Колво;
		Сообщение.Сообщить();	
		
		Возврат Рез;
	КонецФункции

               (Имена пользовательских процедур/функций строятся по принципу Событие_ТипКонтекста_ИмяМетода).

Как работает перехват?

    Предлагаю для простоты считать, что мы имеем дело с объектом Запрос. Как сказано выше, перехват устанавливается глобально на весь рабочий процесс, в котором он вызван, а это значит, что все базы, которые подключены к этому процессу будут иметь дело с измененным методом "IContextExtImpBase::call" интерфейса. В момент вызова какого-либо метода объекта Запрос, выполняется поиск обработки с именем '_proxyInterceptor' в соответствующей базе. Если таковая существует, то выполняется поиск экспортного метода 'ВызватьПерехватчик'. Далее либо отрабатывает переопределенный метод из обработки 'ОбработчикПерехвата', либо выполняется вызов оригинального метода. Если обработки '_proxyInterceptor' не существует, то происходит вызов оригинального метода.

    Важно (1)! Чтобы упростить реализацию, я предполагаю, что право на использование обработки '_proxyInterceptor' есть у каждого пользователя, во всех базах, где она присутствует. Это критично. Если это не так хотя бы для какого-то пользователя, в какой-либо базе, где есть эта обработка, то произойдет перезагрузка серверного процесса (если будет использован объект Запрос). Так же имеет смысл выдать право на использование обработки  "ОбработчикПерехвата'. В случае отсутствия прав у пользователя, будет просто вызван стандартный метод.

    Важно (2)! Всё вышесказанное, тестировалось на релизе 8.3.9.1818. Скорее всего, на релизах 8.3.9.xxxx тоже будет работать (требует проверки). Про поддержку других релизов имеет смысл говорить, когда будет понимание, нужна ли данная "конструкция" вообще.

Ограничения.

    Что не удалось реализовать? "Нормальную" обработку 1С-х исключений. (Тут я привожу технические подробности, для понимания процесса.) В момент, когда тестовая база была практически готова, выяснилось, что при возникновении 1С-го исключения (например синтаксическая ошибка в тексте запроса) всё рушилось, т.е. рабочий процесс на сервере перегружался.

Поэтому, пришлось сделать рефакторинг 1С-го кода и обернуть критичные участки в Попытка...Исключение.

Далее. Если ошибка возникла при обработке оригинального события,              

	Рез = Перехватчик.ВыполнитьОригинальноеСобытие();

то устанавливается "флаг" ошибки и, уже в бинарном коде, повторно вызывается оригинальное событие, чтобы сгенерировать 1С-е исключение.

Если ошибка произошла внутри модуля обработчика, например, внутри функции,

	Функция Событие_Запрос_Выполнить(Запрос) Экспорт 
		.
		.
		.
	КонецФункции

то выводится просто сообщение об ошибке, выполнение при этом не прекращается. Пока мне не удалось это как-то обойти.

    Важно (3)! Заметил такой нюанс: если запустить какое-нибудь длительное фоновое задание, например, перепроведение документов, и в нём выводить тексты Запросов, то это может привести к перезагрузке рабочего процесса, поскольку просто переполняется очередь сообщений, а объёмный текст и количество запросов этому способствуют. В этой связи я делаю проверку на тип клиента при выводе текста.

    В заключении, хочу обратить внимание на ряд технических моментов, которые могут быть полезны при использовании DynamicWrapperX. Должен сказать, что с момента выхода DynamicWrapperX под x64, прошло более 2-х лет. И до последнего времени я и сам на x64-серверах  ничего путного, кроме как Sleep, не использовал. Здесь, в тестовой базе, можно посмотреть другие варианты применения этого Com-объекта. Например, передача параметров через "слой" 'бинарный код-1С' и наоборот, получение функций-оберток, использование интерфейсов COM-объектов, прочее.

Резюмируя вышесказанное.

Чтобы посмотреть, как это работает, необходимо:

  1. Тестовый сервер с релизом 8.3.9.1818.
  2. DynamicWrapperX (http://dynwrapx.script-coding.com/dwx/pages/dynwrapx.php). Вам нужна версия для x64. Ее необходимо зарегистрировать на сервере.
  3. Установить прилагающуюся тестовую базу.
  4. Запустить тонкого клиента и в меню Сервис выбрать обработку Тест.
  5. Включить перехват (соответствующая кнопка).
  6. Протестировать перехват объекта Запрос. (Кнопка 'Тест запроса').

Для других баз:

  1. Скопировать в базу общий модуль DWX_Информатор (галка сервер).
  2. копировать 2 обработки _proxyInterceptor и ОбработчикПерехвата. Выдать права на использование обработок всем пользователям.
  3. В тестовой базе включить перехват.
  4. Если обе базы (тестовая и данная) подцеплены к одному рабочему процессу, то в окне сообщений можно увидеть результат перехвата.

Вступайте в нашу телеграмм-группу Инфостарт

DynamicWrapperX x64 goAsm перехват ассемблер

См. также

Инструментарий разработчика Чистка данных Свертка базы Инструменты администратора БД Системный администратор Программист Руководитель проекта 1С:Предприятие 8 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 3.0 Россия Платные (руб)

Инструмент представляет собой обработку для проведения свёртки или обрезки баз данных. Работает на ЛЮБЫХ конфигурациях (УТ, БП, ERP, УНФ, КА и т.д.). Поддерживаются серверные и файловые базы, управляемые и обычные формы. Может выполнять свертку одновременно в несколько потоков. А так же автоматически, без непосредственного участия пользователя. Решение в Реестре отечественного ПО

24900 руб.

20.08.2024    68263    357    164    

313

Инструментарий разработчика Роли и права Запросы СКД Программист Руководитель проекта 1С:Предприятие 8 Платные (руб)

Инструменты для разработчиков 1С 8.3: Infostart Toolkit. Автоматизация и ускорение разработки на управляемых формах. Легкость работы с 1С.

16500 руб.

02.09.2020    258818    1430    421    

1165

Пакетная печать Печатные формы Инструментарий разработчика Программист 1С:Предприятие 8 Платные (руб)

Расширение для создания и редактирования печатных форм в системе 1С:Предприятие 8.3. Благодаря конструктору можно значительно снизить затраты времени на разработку печатных форм, повысить качество и прозрачность разработки, а также навести порядок в многообразии корпоративных печатных форм. Обновление версии от 21.04.26

22570 руб.

06.10.2023    38241    107    46    

122

Инструментарий разработчика Нейросети Платные (руб)

Первые попытки разработки на 1С с использованием больших языковых моделей (LLM) могут разочаровать. LLMки сильно галлюцинируют, потому что не знают устройства конфигураций 1С, не знают нюансов синтаксиса. Но если дать им подсказки с помощью MCP, то результат получается кардинально лучше. Далее в публикации: MCP для поиска по метаданным 1С, справке синтакс-помощника и проверки синтаксиса.

15250 руб.

25.08.2025    55083    111    29    

123

Инструменты администратора БД Инструментарий разработчика Роли и права Программист 1С:Предприятие 8 1C:Бухгалтерия Россия Платные (руб)

Расширение позволяет без изменения кода конфигурации выполнять проверки при вводе данных, скрывать от пользователя недоступные ему данные, выполнять код в обработчиках. Не изменяет данные конфигурации, легко устанавливается практически на любую конфигурацию на управляемых формах.

17000 руб.

10.11.2023    25286    93    46    

102

Мастера заполнения Поиск данных Инструментарий разработчика Подбор и обработка объектов 1С 8.3 1С 8.5 Платные (руб)

Infostart MagicInput улучшает подбор в полях ввода 1С: ищет по любой части названия и по нескольким ключевым фрагментам, распознаёт ввод в другой раскладке и показывает иконки/статусы объектов прямо в списке. Поддерживает вставку навигационной ссылки/представления документа для автоподбора; для разработчиков доступны поиск по GUID и полному имени предопределённого. Работает в управляемых формах и подключается в большинстве конфигураций 1С 8.3/8.5.

6000 руб.

25.02.2026    3660    13    1    

16

Инструментарий разработчика Программист 1С:Предприятие 8 Платные (руб)

Инструмент для написания и отладки кода в режиме «1С:Предприятие». Представляет собой консоль кода с возможностью пошаговой отладки, просмотра значений переменных любых типов, использования процедур и функций, просмотра стека вызовов, вычисления произвольных выражений на встроенном языке в контексте точки останова, синтаксического контроля и остановки по ошибке. В консоли используется удобный редактор кода с подсветкой, контекстной подсказкой, возможностью вызова конструкторов запроса и форматной строки. 1.3.11 Доработан механизм контекстной подсказки по метаданным

9500 руб.

17.05.2024    52902    182    63    

216
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. bulpi 218 24.03.17 13:35 Сейчас в теме
Автор, конечно, гигант, но практическая ценность сомнительна.
m.s.moiseev; +1 Ответить
2. МимохожийОднако 142 29.03.17 08:41 Сейчас в теме
Хотелось бы примеры практического использования
3. so-quest 140 29.03.17 12:03 Сейчас в теме
Оригинально. Респект за такое.
chessman; +1 Ответить
4. chessman 194 29.03.17 12:58 Сейчас в теме
Как, в общем-то, правильно отметили, «труд», в большей степени, представляет теоретический интерес.
В качестве практического инструмента, на мой взгляд, можно было бы собирать статистику по выполняемым Запросам. Как вариант, записывать тексты запросов, время выполнения, размер выборки, дату, пользователя, для дальнейшего анализа.
То, что касается общего модуля DWX_Информатор, как я уже упоминал, его можно использовать самостоятельно. Например, для создания более универсальных алгоритмов. Допустим, к нам в процедуру приехал Объект. Нам нужно вызвать его экспортный метод «Метод1()», но мы не знаем, есть ли он у Объекта. Кроме как через Попытка…Исключение, сейчас понять это нельзя (поправьте, если ошибаюсь). Выглядит это несколько коряво. Используя DWX_Информатор, это можно сделать.
Думаю, что данный опус, также может быть полезен в качестве примера использования ассемблера. Возможно, это кого-то вдохновит на дальнейшие исследования.
5. sashocq 195 03.04.17 00:10 Сейчас в теме
Интересное исследование.

Есть база КА 2.2. Периодически в ЖР проскакивают записи с непонятным именем события. Можно ли как-то с помощью этого DynamicWrapperX перехватывать каждый вызов ЗаписьЖурналаРегистрации() и залоггировать его контекст выполнения и значения параметров?
6. chessman 194 03.04.17 23:16 Сейчас в теме
(5) Александр, у меня сейчас нет физической возможности проверить это на x64, но на x32 перехват работает.
Тут нужно понимать, что ловятся именно вызовы ЗаписьЖурналаРегистрации(), т.е. если в тексте модуля был вызван этот глобальный метод. Стандартная запись событий сюда не попадает.
То, что касается контекста выполнения, то пока помочь не смогу, хотя сам по себе вопрос довольно актуальный.

Чтобы заработал перехват в Вашем случае, нужно сделать отдельную сборку, поскольку речь идет о перехвате методов Глобальных контекстов. Сделать это не сложно, так что если интересно пишите.
avishnya; sashocq; +2 Ответить
7. sashocq 195 04.04.17 14:16 Сейчас в теме
(6) Владимир, именно это и нужно. Подозреваю, что где-то в коде неправильное имя события передаётся. Простой визуальный осмотр результатов поиска ЗаписьЖурналаРегистрации ничего не дал, т. к. ооочень много кода.

Спасибо, пока добавлю в закладки на будущее. Сейчас слишком большая загрузка по проектам, а вопрос этот не критичный.
8. пользователь 22.12.23 19:50
Сообщение было скрыто модератором.
...
9. пользователь 22.12.23 19:57
Сообщение было скрыто модератором.
...
Для отправки сообщения требуется регистрация/авторизация