При создании файлов поставки или обновлений конфигурации «1С:Предприятие» разработчики часто сталкиваются со следующей проблемой: процесс сборки аварийно прерывается ошибкой компиляции общего модуля. Сообщение выглядит так: «Общий модуль ИмяМодуля.Модуль: в защищенном модуле обнаружены ошибки компиляции. Скомпилированный образ модуля не может быть создан». При этом обычная проверка конфигурации не выдает никаких замечаний, а в режиме «1С:Предприятие» все функции работают корректно.
В этой статье мы подробно проанализируем ситуацию, выясним причину такого поведения платформы и разберем по шагам, как локализовать и устранить эту ошибку, даже если ваш модуль содержит тысячи строк кода.
Когда мы создаем файл поставки конфигурации и выбираем опцию поставки без исходных текстов модулей (то есть создаем защищенный модуль, компилируя его в байт-код), компилятор 1С применяет гораздо более жесткие правила проверки, чем при обычном запуске или стандартном синтаксическом контроле.
Рассмотрим подробнее три главные причины сбоя создания скомпилированного образа:
Клиент (управляемое приложение), Сервер и Внешнее соединение), компилятор пытается собрать единый работоспособный байт-код для каждого из этих контекстов. Если в коде встречается метод или объект, недоступный хотя бы в одном из них (например, интерактивные функции во внешнем соединении или серверные процедуры на веб-клиенте), компиляция образа завершится ошибкой.#Если Сервер Тогда, #Если Клиент Тогда и т. д.). Наличие таких инструкций делает невозможным создание монолитного скомпилированного образа без исходного текста.Внешнее соединение или Веб-клиент остаются «невидимыми» до момента сборки поставки.---
Чтобы увидеть конкретные строки, в которых компилятор обнаружил несовместимость, нам необходимо временно перенастроить синтаксический контроль в конфигураторе и запустить полную проверку. Выполним следующие действия вместе:
Тонкий клиентВеб-клиентСерверВнешнее соединениеТолстый клиент (управляемое приложение)Толстый клиент (обычное приложение)После выполнения этих шагов в окне «Служебные сообщения» вы увидите детальный список ошибок с указанием конкретных строк. Например, вы можете обнаружить предупреждения следующего вида:
Процедура или функция с указанным именем не определена (Предупреждение)
Процедура ВыполнитьДействие() Экспорт
// Ошибка компиляции для контекста: Внешнее соединение
Предупреждение("Действие выполнено!");
КонецПроцедуры
Такой код успешно работает на клиенте, но гарантированно ломает компиляцию защищенного модуля, так как в контексте Внешнее соединение функции интерактивного взаимодействия (такие как Предупреждение или Сообщить) физически отсутствуют.
---
Если в процессе анализа вы обнаружили, что в общем модуле используются директивы препроцессора или смешанный контекст выполнения, лучшим решением будет рефакторинг кода. Проанализируем правильную архитектуру разделения общего модуля.
Вместо одного гигантского общего модуля, в свойствах которого включены все галочки контекста, создайте несколько модулей с узкой специализацией:
Клиент (управляемое приложение). Исходный код этого модуля обычно не закрывают, так как на клиенте не должно содержаться секретных алгоритмов.Сервер (и при необходимости Вызов сервера). В этом модуле располагается вся основная бизнес-логика. Именно этот модуль можно безболезненно закрыть паролем и поставлять без исходных текстов, так как компилятору сервера не нужно будет заботиться о клиентском контексте.Посмотрим на пример неправильного написания кода внутри защищаемого модуля:
// НЕПРАВИЛЬНО: Использование директив препроцессора в закрытом модуле
#Если Сервер Тогда
Функция РассчитатьСкидку(Сумма) Экспорт
Возврат Сумма * 0.05;
КонецФункции
#КонецЕсли
Для исправления этой ситуации мы должны полностью отказаться от директив #Если... внутри защищаемого модуля. Перенесите код функции РассчитатьСкидку в модуль, у которого в свойствах жестко прописано выполнение только на сервере. Пример правильной реализации:
// ПРАВИЛЬНО: Код серверного общего модуля "ИмяМодуляСервер" (без директив препроцессора)
// В свойствах модуля на уровне метаданных включен только флаг "Сервер"
Функция РассчитатьСкидку(Сумма) Экспорт
Возврат Сумма * 0.05;
КонецФункции
---
Что делать, если архитектура вашей конфигурации слишком сложна, модуль содержит тысячи строк кода и его оперативный рефакторинг невозможен, но защитить интеллектуальную собственность от конечного клиента необходимо прямо сейчас?
В таких случаях стандартный механизм 1С «Поставка без исходных текстов» можно временно заменить механизмом обфускации кода. Обфускация — это процесс запутывания исходного кода, при котором логика работы программы полностью сохраняется, но сам текст становится абсолютно нечитаемым для человека.
Сравним пример исходного кода и кода после прохождения простейшего обфускатора:
Исходный код до обфускации:
Функция ПолучитьПроцентнуюСтавку(Клиент) Экспорт
Если Клиент.Надежный Тогда
Возврат 10;
Иначе
Возврат 15;
КонецЕсли;
КонецФункции
Код после обфускации:
Функция _о1(о2) Экспорт Если о2._о3 Тогда Возврат 10; Иначе Возврат 15; КонецЕсли; КонецФункции
Использование специализированных сторонних обфускаторов для языка 1С позволяет:
#Если...).Используя приведенные методики синтаксического контроля и разделения контекстов, вы легко решите проблему компиляции защищенных образов модулей и обеспечите стабильную сборку файлов поставки вашей конфигурации.