При активном расширении возможностей платформы 1С:Предприятие 7.7 с помощью внешних компонент 1С++ и FormEx разработчики периодически сталкиваются с трудноуловимыми ошибками взаимодействия с табличной частью документов. Одной из таких проблем является ситуация, когда стандартный вызов метода НоваяСтрока() в контексте формы перестает добавлять строки либо добавление визуально и программно игнорируется платформой (например, при вводе на основании или заполнении формы извне).
Разберем детально, почему возникает подобный сбой, как на него влияют низкоуровневые механизмы перехвата методов, и какими путями можно гарантированно восстановить работоспособность функционала.
Проанализируем механику работы платформы и внешних библиотек. В штатной модели 1С 7.7 вызов метода НоваяСтрока() через контекст формы нового или еще не отрисованного документа (например, при открытии через ОткрытьФорму() с передачей контекста) часто блокируется: внутренняя привязка таблицы к элементу диалога еще не завершена.
Компонента 1С++ предоставляет специальный оптимизирующий механизм — ТурбоБЛ. Он перехватывает внутреннюю таблицу виртуальных методов ядра платформы и направляет вызовы напрямую, минуя часть медленного стандартного интерпретатора. Если параллельно используется компонента FormEx (перехватывающая оконные процедуры и события интерфейса) или сторонние модули компиляции, возникает так называемый конфликт цепочек перехватов (Hook Chaining):
Посмотрим на практическое решение проблемы через изменение состояния механизма ТурбоБЛ. Для программного управления низкоуровневыми опциями в 1С++ существует специальный класс УправлениеНастройками. Если метод НоваяСтрока() перестал отрабатывать, включение или выключение данного механизма позволяет стабилизировать поведение контекста документа.
Разберем пример инициализации настройки:
// Управление перехватом методов через 1С++
гУправлениеНастройками = СоздатьОбъект("УправлениеНастройками");
гУправлениеНастройками.Установить("ТурбоБЛ", псВключить);
Обратим внимание на ключевые особенности работы этого механизма:
Установить() можно вызывать в процессе работы, полное и корректное снятие хуков ядра на лету архитектурно затруднено. Если перехват отключается динамически, внутренние адреса функций ядра могут остаться частично модифицированными, что приводит к непредсказуемому поведению в отдельных документах (например, в «Приходной накладной» или «Перемещении»). Настройки надежнее задавать в глобальном модуле при старте системы.УправлениеНастройками сохраняется в реестре текущего пользователя Windows. Поэтому изменение настройки в одной базе может повлиять на запуск других баз 1С на этом же рабочем месте.Проанализируем связку версий внешних компонент. На практике часто наблюдается несовместимость определенных сборок FormEx и 1С++. В частности, нестабильное поведение метода НоваяСтрока() наблюдается при сочетании FormEx версии 2.0.5.94 со старыми релизами 1С++. Стабильной конфигурацией в большинстве случаев является использование FormEx сборки 109 в сочетании с актуальным релизом 1С++ при выключенном либо корректно инициализированном «ТурбоБЛ».
Также критически важен порядок загрузки библиотек в процедуре ПриНачалеРаботыСистемы() глобального модуля:
1cpp.dll), так как она модифицирует ядро компилятора и работу с типами данных.formex.dll), которая встраивается в оконную подсистему и визуальные элементы.Соблюдение этой последовательности исключает разрушение цепочки перехвата функций в оперативной памяти процесса 1cv7s.exe.
Если специфика проекта не позволяет полностью перенастроить внешние компоненты или отключение «ТурбоБЛ» замедляет другие критичные участки кода, применим архитектурный обход проблемы. Исключим прямое обращение к методам открывающейся формы через внешний переданный контекст.
Рассмотрим два безопасных сценария:
КонтекстДокумента.НоваяСтрока() из внешней обработки или журнала, сформируем структуру данных заранее и передадим ее третьим параметром команды открытия:
// В вызывающем модуле формируем Таблицу Значений с нужными данными
ТЗ = СоздатьОбъект("ТаблицаЗначений");
// ... заполняем колонки Номенклатура, Количество, Сумма ...
// Открываем форму с передачей данных в параметре
ОткрытьФорму("Документ.Перемещение", ТЗ);
ПриОткрытии() считываем переданную структуру и штатно заполняем табличную часть изнутри собственного контекста:
Процедура ПриОткрытии()
Если ТипЗначенияСтр(Форма.Параметр) = "ТаблицаЗначений" Тогда
// Загрузка строк выполняется надежно внутри своего контекста
ЗагрузитьТабличнуюЧасть(Форма.Параметр);
КонецЕсли;
КонецПроцедуры
ВводНаОсновании(ДокументОснование). В этой точке выполнение происходит на уровне самого бизнес-объекта до создания графических окон, где метод НоваяСтрока() всегда отрабатывает штатно и не зависит от оконных перехватов FormEx.Если сбои происходят только на рабочих станциях под управлением Windows 7 и выше, а на Windows XP все работает стабильно, настроим исключения безопасности Windows:
1cv7s.exe и 1cv7.exe в список исключений DEP.