Почему не работает метод НоваяСтрока() в модуле формы 1С 7.7 при использовании 1С++ и FormEx?

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

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

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

Причины сбоя: конфликт хуков и механизм «ТурбоБЛ»

Проанализируем механику работы платформы и внешних библиотек. В штатной модели 1С 7.7 вызов метода НоваяСтрока() через контекст формы нового или еще не отрисованного документа (например, при открытии через ОткрытьФорму() с передачей контекста) часто блокируется: внутренняя привязка таблицы к элементу диалога еще не завершена.

Компонента 1С++ предоставляет специальный оптимизирующий механизм — ТурбоБЛ. Он перехватывает внутреннюю таблицу виртуальных методов ядра платформы и направляет вызовы напрямую, минуя часть медленного стандартного интерпретатора. Если параллельно используется компонента FormEx (перехватывающая оконные процедуры и события интерфейса) или сторонние модули компиляции, возникает так называемый конфликт цепочек перехватов (Hook Chaining):

  1. Одна библиотека перетирает точку входа в перехваченную функцию ядра без корректной передачи управления следующему обработчику.
  2. Указатель на текущую строку документа теряется или обращается к неинициализированной области памяти, из-за чего добавление строки дает сбой.
  3. В операционных системах Windows 7, Windows Server 2008 и выше вмешиваются механизмы безопасности: аппаратный DEP (Data Execution Prevention) и ASLR. Старые версии библиотек создавали машинный код перехватов («трамплины») прямо в сегментах данных, что в современных ОС блокируется и вызывает скрытые ошибки при работе перехватчиков.

Способ 1. Управление параметром «ТурбоБЛ» через объект настроек 1С++

Посмотрим на практическое решение проблемы через изменение состояния механизма ТурбоБЛ. Для программного управления низкоуровневыми опциями в 1С++ существует специальный класс УправлениеНастройками. Если метод НоваяСтрока() перестал отрабатывать, включение или выключение данного механизма позволяет стабилизировать поведение контекста документа.

Разберем пример инициализации настройки:


// Управление перехватом методов через 1С++
гУправлениеНастройками = СоздатьОбъект("УправлениеНастройками");
гУправлениеНастройками.Установить("ТурбоБЛ", псВключить);

Обратим внимание на ключевые особенности работы этого механизма:

  1. Динамическое переключение: Хотя метод Установить() можно вызывать в процессе работы, полное и корректное снятие хуков ядра на лету архитектурно затруднено. Если перехват отключается динамически, внутренние адреса функций ядра могут остаться частично модифицированными, что приводит к непредсказуемому поведению в отдельных документах (например, в «Приходной накладной» или «Перемещении»). Настройки надежнее задавать в глобальном модуле при старте системы.
  2. Хранение параметров: Состояние параметров объекта УправлениеНастройками сохраняется в реестре текущего пользователя Windows. Поэтому изменение настройки в одной базе может повлиять на запуск других баз 1С на этом же рабочем месте.

Способ 2. Подбор стабильных версий библиотек и порядок их загрузки

Проанализируем связку версий внешних компонент. На практике часто наблюдается несовместимость определенных сборок FormEx и 1С++. В частности, нестабильное поведение метода НоваяСтрока() наблюдается при сочетании FormEx версии 2.0.5.94 со старыми релизами 1С++. Стабильной конфигурацией в большинстве случаев является использование FormEx сборки 109 в сочетании с актуальным релизом 1С++ при выключенном либо корректно инициализированном «ТурбоБЛ».

Также критически важен порядок загрузки библиотек в процедуре ПриНачалеРаботыСистемы() глобального модуля:

  1. Первой всегда должна загружаться компонента 1С++ (1cpp.dll), так как она модифицирует ядро компилятора и работу с типами данных.
  2. Второй загружается компонента FormEx (formex.dll), которая встраивается в оконную подсистему и визуальные элементы.

Соблюдение этой последовательности исключает разрушение цепочки перехвата функций в оперативной памяти процесса 1cv7s.exe.

Способ 3. Архитектурный обход: передача данных без зависимости от хуков

Если специфика проекта не позволяет полностью перенастроить внешние компоненты или отключение «ТурбоБЛ» замедляет другие критичные участки кода, применим архитектурный обход проблемы. Исключим прямое обращение к методам открывающейся формы через внешний переданный контекст.

Рассмотрим два безопасных сценария:

  1. Передача таблицы данных через параметр формы: Вместо последовательного вызова КонтекстДокумента.НоваяСтрока() из внешней обработки или журнала, сформируем структуру данных заранее и передадим ее третьим параметром команды открытия:
    
    // В вызывающем модуле формируем Таблицу Значений с нужными данными
    ТЗ = СоздатьОбъект("ТаблицаЗначений");
    // ... заполняем колонки Номенклатура, Количество, Сумма ...
    
    // Открываем форму с передачей данных в параметре
    ОткрытьФорму("Документ.Перемещение", ТЗ);
    
    В модуле формы самого открываемого документа в предопределенной процедуре ПриОткрытии() считываем переданную структуру и штатно заполняем табличную часть изнутри собственного контекста:
    
    Процедура ПриОткрытии()
        Если ТипЗначенияСтр(Форма.Параметр) = "ТаблицаЗначений" Тогда
            // Загрузка строк выполняется надежно внутри своего контекста
            ЗагрузитьТабличнуюЧасть(Форма.Параметр);
        КонецЕсли;
    КонецПроцедуры
    
  2. Использование предопределенной процедуры «ВводНаОсновании»: Если документ создается на базе другого объекта, логику добавления строк следует перенести в предопределенную процедуру модуля документа ВводНаОсновании(ДокументОснование). В этой точке выполнение происходит на уровне самого бизнес-объекта до создания графических окон, где метод НоваяСтрока() всегда отрабатывает штатно и не зависит от оконных перехватов FormEx.

Настройка операционной системы (DEP)

Если сбои происходят только на рабочих станциях под управлением Windows 7 и выше, а на Windows XP все работает стабильно, настроим исключения безопасности Windows:

  1. Откроем свойства системы и перейдем в раздел «Предотвращение выполнения данных» (DEP).
  2. Добавим исполняемые файлы платформы 1cv7s.exe и 1cv7.exe в список исключений DEP.
  3. Это позволит компонентам 1С++ и FormEx корректно создавать необходимые трамплины машинного кода в оперативной памяти без блокировки со стороны системы.
← На главную