Почему возникает аварийное завершение 1С при работе с макетами в расширении и как это исправить?

Программист 1С v8.3 (Управляемые формы) 1С:Управление торговлей IT и автоматизация бизнеса
← На главную

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

Выясним причины падения платформы

Проанализируем механику работы расширений с макетами, чтобы понять истоки проблемы:

  1. Ошибка механизма слияния макетов в платформе. В версиях платформы линейки 8.3.10 (в частности, 8.3.10.2252) механизм сопоставления заимствованных табличных документов содержал платформенную ошибку. При попытке объединить исходный табличный документ с изменениями из расширения (особенно если макет содержит объединенные ячейки, параметры, рисунки или штрихкоды) происходил сбой внутренней библиотеки работы с табличными документами, вызывавший аварийное завершение клиентского приложения или рабочего процесса сервера rphost.
  2. Попытка заимствования двоичных макетов (DOCX, ODT). Заимствование макетов на основе двоичных файлов на многих релизах платформы гарантированно приводит к фатальным ошибкам. Механизм расширения рассчитан на вычисление разницы ячеек для табличных документов (MXL). Для файлов Word или OpenOffice поклеточное объединение невозможно на уровне платформы, что и провоцирует аварийный останов при обращении к ресурсу.
  3. Специфика видимости макетов в контексте менеджера объекта. Если макет добавлен как подчиненный объект к заимствованному документу или справочнику, платформа может корректно отображать его в дереве метаданных конфигуратора и в механизме автодополнения кода, но контекст менеджера объекта в режиме предприятия не регистрирует его в сеансовом пространстве имен. Попытка вызова метода ПолучитьМакет() в таком случае вызывает исключение «Недопустимое значение параметра».
  4. Серверное кэширование метаданных. Ситуация, когда база продолжает падать даже после отключения расширения, обусловлена кэшированием скомпилированной структуры метаданных на сервере «1С:Предприятия». Пока процесс rphost удерживает старое состояние схемы данных в памяти, ошибка повторяется при любом вызове связанной функциональности.

Способ 1. Создание нового макета в расширении и переопределение вызова через аннотацию «&Вместо»

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

Рассмотрим пошаговый алгоритм реализации:

  1. Заимствуем в расширение объект метаданных (документ, справочник или обработку печати), для которого требуется изменить печатную форму.
  2. Не заимствуем типовой макет через контекстное меню. Вместо этого создаем внутри заимствованного объекта новый макет (или копируем содержимое типового макета в новый пустой макет) и задаем ему имя с префиксом расширения, например: Расш1_ПФ_MXL_Накладная или РасшСчет_Макет.
  3. Вносим все необходимые визуальные и структурные изменения в созданный макет расширения.
  4. Заимствуем модуль менеджера документа или обработки печати в расширение с возможностью добавления методов.
  5. Переопределяем функцию, возвращающую путь к макету или формирующую печатную форму, с помощью аннотации &Вместо.

Посмотрим на пример переопределения функции определения пути к макету в модуле менеджера заимствованной обработки печати:


&Вместо("ПолныйПутьКМакету")
Функция РасшСчет_ПолныйПутьКМакету() Экспорт
    
    // Возвращаем путь к собственному макету, созданному внутри расширения
    Возврат "Обработка.ПечатьСчетНаОплату.РасшСчет_Макет";
    
КонецФункции

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


&Вместо("СформироватьПечатнуюФорму")
Функция Расш1_СформироватьПечатнуюФорму(МассивОбъектов, ОбъектыПечати)
    
    // Получаем макет, созданный непосредственно в объекте расширения
    Макет = УправлениеПечатью.МакетПечатнойФормы("Документ.КоммерческоеПредложениеКлиенту.Расш1_ПФ_MXL_КоммерческоеПредложение");
    
    ТабличныйДокумент = Новый ТабличныйДокумент;
    // Заполнение областей макета данными
    
    Возврат ТабличныйДокумент;
    
КонецФункции

Способ 2. Использование общих макетов расширения

Если макет подчиненного объекта не определяется платформой внутри менеджера или если требуется использовать макет двоичных данных (DOCX, ODT), оптимальным решением является создание Общего макета в составе самого расширения.

  1. В дереве метаданных расширения конфигурации переходим в ветку Общие — Общие макеты.
  2. Добавляем новый общий макет, задаем ему имя с префиксом (например, Расш1_ПФ_DOCX_ДоговорПоставки) и загружаем в него шаблон документа.
  3. В коде формирования печатной формы обращаемся к общему макету напрямую:

// Для табличных и двоичных документов через системный метод
ДвоичныеДанныеМакета = ПолучитьОбщийМакет("Расш1_ПФ_DOCX_ДоговорПоставки");

// Либо при формировании пути для подсистемы печати БСП
ПутьКМакету = "ОбщийМакет.Расш1_ПФ_DOCX_ДоговорПоставки";
Макет = УправлениеПечатью.МакетПечатнойФормы(ПутьКМакету);

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

Способ 3. Переключение свойства «Способ расширения» на «Замещать»

Если логика доработки требует именно заимствования существующего макета табличного документа под тем же именем, обратим внимание на его палитру свойств в расширении. По умолчанию для заимствованного макета свойство Способ расширения установлено в значение Объединять. Именно режим объединения провоцирует сбой библиотеки moxel.dll.

  1. Открываем палитру свойств заимствованного макета в расширении конфигурации.
  2. Находим свойство Способ расширения.
  3. Изменяем значение с Объединять на Замещать.

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

Особенности взаимодействия с подсистемой печати БСП

При использовании Библиотеки Стандартных Подсистем (БСП) важно учитывать работу регистра сведений пользовательских макетов печати:

  1. Метод УправлениеПечатью.МакетПечатнойФормы() в первую очередь проверяет наличие отредактированной версии макета в информационной базе. Если пользователь ранее изменял печатную форму в режиме предприятия (раздел Администрирование — Печатные формы, отчеты и обработки — Макеты печатных форм), платформа проигнорирует версию из расширения и загрузит макет из базы. В такой ситуации необходимо нажать кнопку Использовать стандартный макет в интерфейсе управления макетами.
  2. При вызове метода УправлениеПечатью.МакетПечатнойФормы() первым параметром всегда должна передаваться строка пути в формате "Документ.ИмяДокумента.ИмяМакета" или "ОбщийМакет.ИмяМакета". Передача ссылки на объект метаданных (Метаданные.Документы...) приводит к ошибке выполнения или возврату значения Неопределено.

Действия при сохранении дампов: очистка серверного кэша

Если после удаления проблемного макета или отключения расширения база продолжает аварийно завершать работу при открытии формы печати, выполним принудительную очистку серверного кэша:

  1. Останавливаем службу агента сервера «1С:Предприятия» (1C:Enterprise Server Agent).
  2. Переходим в рабочий каталог кластера сервера (по умолчанию для 64-битной версии: C:\Program Files\1cv8\srvinfo\reg_1541).
  3. Удаляем каталоги сеансовых данных и кэша метаданных, начинающиеся на snccntx*. Каталоги базы данных и журналы регистрации при этом не затрагиваются.
  4. Очищаем каталоги локального кэша тонкого клиента на компьютере разработчика (папки 1cv8 внутри %AppData% и %LocalAppData%).
  5. Запускаем службу агента сервера и выполняем повторное тестирование печати.
← На главную