При работе с платформой 1С:Предприятие 8.3 программисты часто сталкиваются с ситуацией, когда код, прекрасно работающий при интерактивном запуске из клиентского приложения, неожиданно завершается с ошибкой при выполнении в фоновом режиме, например, в регламентном задании. Одна из наиболее распространенных ошибок в таком сценарии — это "Ошибка инициализации модуля". Давайте рассмотрим подробнее, почему возникает такая ситуация и как ее эффективно исправить.
Основная причина такого поведения кроется в фундаментальном различии между клиентским и серверным контекстами выполнения кода в 1С. Мы всегда должны помнить, что:
Если в коде, который должен выполняться на сервере (например, в модуле обработки, вызываемой регламентным заданием), присутствуют функции, предназначенные исключительно для клиентского контекста, система не сможет инициализировать этот модуль на сервере. Это логично: сервер просто не знает, как отобразить "Предупреждение" или обновить "Состояние" в строке, потому что у него нет пользовательского интерфейса. В результате мы получаем ту самую "Ошибка инициализации модуля".
Как показывает опыт и подтверждает данная проблема, чаще всего причиной являются следующие функции:
Предупреждение(): Этот метод выводит модальное окно с сообщением пользователю. На сервере его использование недопустимо, так как нет пользователя, которому можно было бы показать это окно.Состояние(): Используется для вывода информации о ходе выполнения операции в строку состояния клиентского приложения. Аналогично, на сервере нет строки состояния.ПоказатьВопрос(), ПоказатьОповещениеПользователя() (хотя для последних версий платформы появились новые механизмы уведомлений с сервера на клиент, они не относятся к регламентным заданиям, которые работают без активного клиентского сеанса и тем более не инициируют ошибку инициализации модуля).Теперь, когда мы понимаем причину, нам нужно найти те самые "запрещенные" функции в нашем коде. К счастью, платформа 1С предоставляет отличный инструмент для этого — "Проверка конфигурации".
Давайте разберем по шагам, как использовать этот инструмент:
В результате проверки вы, скорее всего, увидите сообщения, подобные следующему:
{МодульОбъекта.НазваниеВашейОбработки(СтрокаКода)}: Использование синхронных методов на клиенте запрещено в модулях сервера
или конкретно:
{МодульОбъекта.НазваниеВашейОбработки(СтрокаКода)}: Метод Предупреждение() доступен только на клиенте
Эти сообщения точно укажут на строку кода и метод, который является причиной ошибки инициализации модуля на сервере.
После того, как "Проверка конфигурации" указала нам на проблемные места, задача становится очевидной: мы должны удалить или заменить клиентские функции в серверном коде. Для автоматического выявления и устранения таких проблем можно применить инструмент для проверки кода по стандартам и автоисправления замечаний.
В нашем примере, первоначальный код регламентного задания выглядел так:
Процедура TradeDealer() Экспорт
Обр = Обработки.TradeDealer.Создать();
Обр.ВыгрузитьВTradeDealer();
КонецПроцедуры
А ошибка инициализации модуля возникла в Обработка.TradeDealer.МодульОбъекта, потому что внутри метода ВыгрузитьВTradeDealer() (или в любом другом методе, вызываемом из него) использовалась функция Предупреждение().
Наш подход к исправлению:
МодульОбъекта обработки TradeDealer) и перейдите к строке, которую выдала "Проверка конфигурации".Предупреждение(), просто удалите ее. Если вам действительно нужно вывести какое-то сообщение пользователю (например, об успешном завершении или об ошибке), то это должно быть сделано в клиентском коде, который вызывает серверный, или через механизмы уведомлений, описанные ниже.Возникает логичный вопрос: если нельзя использовать Предупреждение() или Состояние() на сервере, как же нам получать информацию о ходе выполнения или об ошибках в регламентном задании? Платформа 1С предлагает несколько надежных механизмов для этого:
// Пример записи в Журнал регистрации
ЗаписьЖурналаРегистрации(
НСтр("ru = 'Выгрузка в TradeDealer'"),
УровеньВажностиЖурналаСобытий.Информация,
,
,
НСтр("ru = 'Выгрузка успешно завершена.'")
);
// Для ошибок:
ЗаписьЖурналаРегистрации(
НСтр("ru = 'Выгрузка в TradeDealer'"),
УровеньВажностиЖурналаСобытий.Ошибка,
Метаданные.Обработки.TradeDealer,
,
НСтр("ru = 'Ошибка при выгрузке: '") + ОписаниеОшибки
);
// Пример записи в Регистр сведений
НаборЗаписей = РегистрыСведений.ЖурналВыгрузок.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Регистратор.Установить(СсылкаНаОбъектВыгрузки); // Если есть регистратор
НоваяЗапись = НаборЗаписей.Добавить();
НоваяЗапись.Дата = ТекущаяДата();
НоваяЗапись.Сообщение = "Выгрузка успешно завершена для объекта " + Объект.Представление;
НоваяЗапись.ТипСобытия = "Успех";
НаборЗаписей.Записать();
// Пример отправки e-mail (требует настройки почтового клиента в 1С)
Почта = Новый ИнтернетПочта();
// ... настройка подключения ...
Сообщение = Новый ИнтернетПочтовоеСообщение();
Сообщение.Получатели.Добавить("admin@example.com");
Сообщение.Тема = "Ошибка регламентного задания 'Выгрузка в TradeDealer'";
Сообщение.Текст = "Внимание! Произошла ошибка при выполнении выгрузки: " + ОписаниеОшибки;
Почта.Послать(Сообщение);
Хотя основной причиной является различие в контекстах, иногда "Ошибка инициализации модуля" может указывать и на другие проблемы:
Таким образом, когда мы сталкиваемся с ошибкой "Ошибка инициализации модуля" в регламентном задании, в первую очередь мы должны сосредоточиться на поиске и устранении клиентских функций в серверном коде, используя инструмент "Проверка конфигурации". После этого, мы можем выбрать наиболее подходящий способ для информирования о событиях, происходящих в фоновых заданиях, опираясь на механизмы, предназначенные для серверного выполнения.