Как программно получить текст сообщений, выведенных через Сообщить в 1С

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

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

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

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

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

Рассмотрим пример кода, который позволяет считать все накопленные сообщения:


// Получаем массив сообщений и очищаем буфер
МассивСообщений = ПолучитьСообщенияПользователю(Истина);

Для Каждого ТекущееСообщение Из МассивСообщений Цикл
    ТекстСообщения = ТекущееСообщение.Текст;
    // Здесь можно выполнить любую логику обработки текста
    ЗаписьЖурналаРегистрации("Инфо",,,,"Текст из Сообщить: " + ТекстСообщения);
КонецЦикла;

Важный нюанс: метод ПолучитьСообщенияПользователю принимает один необязательный параметр — УдалятьПолученные (тип Булево). Если мы передаем Истина, то после вызова метода очередь сообщений очищается, и пользователь их в стандартном окне внизу экрана уже не увидит. Если же передать Ложь, мы получим текст программно, но сообщения все равно отобразятся в интерфейсе.

Структура данных сообщения

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

  1. Текст — собственно само сообщение.
  2. Поле — строка, указывающая на конкретный реквизит формы, к которому привязано сообщение.
  3. ПутьКДанным — путь к объекту данных (например, к реквизиту объекта).
  4. КлючДанных — ссылка на объект, к которому относится уведомление.

Это позволяет нам не только получить текст, но и понять, в контексте какого поля возникла та или иная ошибка или информационное сообщение.

Различия между обычным и управляемым приложением

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

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

Перехват сообщений в фоновых заданиях

Проанализируем ситуацию с фоновыми заданиями. Когда код выполняется на сервере в рамках фонового задания, функции Сообщить() не выводят данные напрямую на экран, так как у задания нет интерфейса. Сообщения накапливаются в буфере задания. Чтобы получить их в родительском сеансе, мы должны использовать метод объекта ФоновоеЗадание.

Пример получения сообщений из фонового задания:


// Допустим, Задание — это объект ФоновоеЗадание
МассивСообщений = Задание.ПолучитьСообщения();

Для Каждого Сообщение Из МассивСообщений Цикл
    Сообщить("Фоновое задание сообщило: " + Сообщение.Текст);
КонецЦикла;

Альтернативный подход: Создание обертки

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

Посмотрим на пример такой процедуры:


Процедура глСообщить(Текст) Экспорт
    // Выводим пользователю
    Сообщить(Текст);
    
    // Дублируем в массив для программного доступа
    ПараметрыСеанса.ПоследниеСообщения.Добавить(Текст);
    
    // Или сразу пишем в текстовый лог
    ЗаписьТекста = Новый ЗаписьТекста("C:\logs\my_log.txt", КодировкаТекста.UTF8, Истина);
    ЗаписьТекста.ЗаписатьСтроку(Строка(ТекущаяДата()) + ": " + Текст);
    ЗаписьТекста.Закрыть();
КонецПроцедуры

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

Критическое замечание о Журнале регистрации

Посмотрим на распространенное заблуждение, упомянутое в обсуждении на форуме. Некоторые разработчики полагают, что Сообщить() автоматически дублирует записи в Журнал регистрации. Это не так. Платформа не пишет обычные сообщения в журнал самостоятельно. Если вам нужно, чтобы информация сохранялась в истории системы, необходимо явно вызывать метод ЗаписьЖурналаРегистрации().

Резюме

Подведем итог. Чтобы получить текст из Сообщить(), мы должны:

  1. Использовать функцию ПолучитьСообщенияПользователю(Ложь), если хотим просто прочитать текст, не скрывая его от пользователя.
  2. Использовать ПолучитьСообщенияПользователю(Истина), если мы берем на себя ответственность за вывод или обработку этих данных.
  3. Помнить, что в фоновых заданиях сообщения считываются через объект задания.
  4. Для максимальной надежности внедрять собственные процедуры-обертки для логирования критически важной информации.
← На главную