Как программно получить сообщения и ошибки из фонового задания 1С?

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

В процессе разработки часто возникает ситуация, когда длительные операции выполняются в фоновом режиме. Если внутри такого фонового задания (ФЗ) происходит ошибка, которая не вызывает исключение, а лишь выводит текст через Сообщить() или СообщениеПользователю и устанавливает Отказ = Истина, разработчик сталкивается с проблемой: как узнать, что именно пошло не так? Поскольку задание выполняется на сервере без участия интерфейса, обычное окно сообщений пользователю не отображается, и в Журнале регистрации эти записи по умолчанию не фиксируются.

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

Способ 1. Использование метода ПолучитьСообщенияПользователю()

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

Разберем по шагам, как это реализовать в коде:

Во-первых, нам необходимо получить объект фонового задания по его уникальному идентификатору. Во-вторых, вызвать метод ПолучитьСообщенияПользователю(). Этот метод возвращает массив объектов типа СообщениеПользователю.


// Пример получения сообщений из фонового задания
ИдентификаторЗадания = Новый УникальныйИдентификатор(СтрокаИдентификатора);
Задание = ФоновыеЗадания.НайтиПоУникальномуИдентификатору(ИдентификаторЗадания);

Если Задание <> Неопределено Тогда
    // Параметр Истина означает, что прочитанные сообщения будут удалены из буфера задания
    МассивСообщений = Задание.ПолучитьСообщенияПользователю(Истина);
    
    Для Каждого ТекущееСообщение Из МассивСообщений Цикл
        ТекстОшибки = ТекущееСообщение.Текст;
        // Здесь мы можем записать текст в Журнал регистрации или вывести пользователю в ГУИ
        ЗаписатьВЖурналРегистрации("ФоновоеЗадание.Ошибка", УровеньЖурналаРегистрации.Ошибка, , , ТекстОшибки);
    КонецЦикла;
КонецЕсли;

Важный нюанс: Параметр УдалятьПолученные играет ключевую роль. Если вы используете обработчик ожидания на форме для мониторинга хода выполнения задания, передавайте Истина. Это позволит вам получать только «новые» сообщения, появившиеся с момента последней проверки, не дублируя старые.

Способ 2. Использование инструментов БСП (Библиотека стандартных подсистем)

Если ваша конфигурация построена на базе БСП, мы рекомендуем использовать программный интерфейс модуля ДлительныеОперации. Это более современный и высокоуровневый подход, который берет на себя часть рутинной работы по управлению фоновыми процессами.

Проанализируем преимущества этого метода:

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

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

Способ 3. Организация внешнего логирования (файлы и регистры)

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

Выясним причину, почему обычная запись в Журнал регистрации или регистр сведений может не сработать. Если ошибка происходит внутри транзакции (например, в процедуре ПередЗаписью), то после установки Отказ = Истина вся транзакция отменяется. Вместе с ней отменяются и все ваши попытки записать лог ошибки в базу данных.

Для решения этой задачи рассмотрим два варианта:

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

Способ 4. Перехват через расширение конфигурации

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

Мы можем создать расширение и добавить обработчик После для процедуры, в которой происходит запись объекта (например, ПередЗаписью или ПриЗаписи). В этом обработчике мы проверяем значение параметра Отказ.


&После("ПередЗаписью")
Процедура Расш_ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
    Если Отказ Тогда
        // Если кто-то в основной конфигурации установил Отказ, 
        // мы можем собрать текущие сообщения в этом же контексте
        МассивСообщений = ПолучитьСообщенияПользователю(Истина);
        Для Каждого Сообщение Из МассивСообщений Цикл
            // Логируем сообщение, которое иначе пропало бы
            ЗаписатьВЖурналРегистрации("ПерехватОшибки", УровеньЖурналаРегистрации.Предупреждение, , , Сообщение.Текст);
        КонецЦикла;
    КонецЕсли;
КонецПроцедуры

Способ 5. Глубокая отладка через Технологический журнал

В самых сложных случаях, когда сообщения генерируются платформенными механизмами или закрытыми модулями, можно прибегнуть к настройке Технологического журнала (ТЖ). Это инструмент системного администратора и разработчика экспертного уровня.

Нам потребуется настроить сбор события SCOM в файле logcfg.xml. Это событие отвечает за коммуникации между сервером и клиентом (в том числе виртуальным клиентом фонового задания). В тексте событий SCOM можно найти передаваемые тексты сообщений. Однако помните, что ТЖ создает значительную нагрузку на дисковую подсистему, поэтому используйте его только для разовой отладки.

Резюме и рекомендации

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

Во-первых, всегда используйте Попытка...Исключение вокруг критических участков кода. Но помните, что СообщениеПользователю — это не исключение, его нужно ловить отдельно.

Во-вторых, если вы пишете свой код для ФЗ, старайтесь возвращать результат выполнения (включая ошибки) через ВременноеХранилище. Это самый надежный способ передать структуру с данными и описанием проблем обратно в вызывающий поток.

В-третьих, активно используйте метод Задание.ПолучитьСообщенияПользователю(Истина) в обработчиках ожидания. Это позволит вашим пользователям видеть прогресс и ошибки загрузки в реальном времени, даже если само задание еще не завершено.

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

← На главную