Что делать, если в серверном коде 1С нужно увидеть значение или текст

· 9 мин

Содержание

Вывести сообщение на сервере 1С можно пятью способами: Новый СообщениеПользователю (или Сообщить()), запись в журнал регистрации через ЗаписьЖурналаРегистрации(), ВызватьИсключение, возврат значения в клиентскую процедуру и запись в текстовый лог-файл. Первый работает только тогда, когда серверный код вызван с клиента: сообщения копятся на сервере и показываются пользователю, как только вызов вернётся на клиент.

Если код выполняется без клиента — регламентное задание, HTTP-сервис, веб-сервис, обработчик обмена, — окна сообщений нет. Там отладочный вывод пишут в журнал регистрации или в файл. Всё ниже относится к платформе 8.3 и управляемому приложению; в файловом варианте «сервер» живёт внутри клиентского процесса, но правила видимости сообщений те же.

Куда уходит сообщение из серверного кода

Серверная процедура не может открыть окно. Предупреждение(), ПоказатьПредупреждение(), Вопрос() — методы клиента, на сервере их вызов даст ошибку ещё при компиляции модуля или при выполнении.

Зато объект СообщениеПользователю на сервере создать можно:

&НаСервере
Процедура ПроверитьОстаткиНаСервере()

    Сообщение = Новый СообщениеПользователю;
    Сообщение.Текст = СтрШаблон("Обработано строк: %1", Формат(Объект.Товары.Количество(), "ЧГ=0"));
    Сообщение.Поле = "Объект.Товары";
    Сообщение.Сообщить();

КонецПроцедуры

Что происходит с таким сообщением в разных контекстах:

Где выполняется кодУвидит ли пользовательКак прочитать
Серверная процедура формы, общий модуль с вызовом сервераДа, после возврата на клиентВ окне сообщений формы
Фоновое заданиеНе сразуФоновоеЗадание.ПолучитьСообщенияПользователю()
Регламентное заданиеНетЖурнал регистрации или файл
HTTP-сервис, веб-сервисНетЖурнал регистрации или файл
Обработчик проведения при программной записи из фонаНетЖурнал регистрации

💡 Сообщения не появляются по одному «в реальном времени». Если серверная процедура крутится 10 минут и пишет 500 сообщений, пользователь увидит их пачкой через 10 минут.

В типовых конфигурациях на БСП удобнее вызывать ОбщегоНазначения.СообщитьПользователю(Текст, КлючДанных, Поле, ПутьКДанным, Отказ). Он работает и на клиенте, и на сервере, а через параметр Поле привязывает сообщение к реквизиту формы: пользователь щёлкает по тексту — курсор встаёт в нужное поле.

Отладка через журнал регистрации

Журнал регистрации — главный инструмент, когда кода «у клиента» нет. Запись делается одной строкой и переживает перезапуск сервера.

ЗаписьЖурналаРегистрации("Обмен.ЗагрузкаЗаказов",
    УровеньЖурналаРегистрации.Информация,
    Метаданные.Документы.ЗаказКлиента,
    ДокументСсылка,
    СтрШаблон("Загружено позиций: %1", Формат(КоличествоСтрок, "ЧГ=0")));

Параметры по порядку:

  1. 📝 Имя события — строка. Задавайте его через точку: Подсистема.Действие. Потом по нему удобно фильтровать.
  2. 🚦 Уровень — Информация, Предупреждение, Ошибка или Примечание.
  3. 🗂 Метаданные — объект конфигурации, к которому относится запись. Можно не указывать.
  4. 🔗 Данные — ссылка на объект. Из журнала по ней можно открыть документ.
  5. 💬 Комментарий — сам текст отладочного вывода. Сюда кладите значения переменных.

В англоязычном синтаксисе метод называется WriteLogEvent. В поиске его часто ищут как «WriteToLog», но такого метода в платформе нет.

Как найти запись

  • В Конфигураторе: Администрирование → Журнал регистрации.
  • В пользовательском режиме «Такси»: Главное меню → Все функции → Стандартные → Журнал регистрации (команда «Все функции» включается в параметрах программы).
  • В БП 3.0, ЗУП 3.1, УТ 11: раздел Администрирование → Обслуживание, группа с протоколами работы программы.

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

Запись внутри транзакции

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

Транзакционный режим (РежимТранзакцииЗаписиЖурналаРегистрации.Транзакционная) пишет запись только при успешной фиксации транзакции. Для поиска причины отката он бесполезен.

Не превращайте журнал в свалку. Запись в цикле на 100 000 строк раздувает журнал на сотни мегабайт и замедляет его открытие для всех. Пишите итог и выборочные значения, а после отладки удаляйте вызовы или переводите их под флаг.

Исключение как способ остановить код и показать текст

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

Если Не ЗначениеЗаполнено(Контрагент) Тогда
    ВызватьИсключение СтрШаблон("Не заполнен контрагент в строке %1", НомерСтроки);
КонецЕсли;

Где это уместно:

  • 🛑 проверка входных данных, после которой продолжать бессмысленно;
  • 🔍 быстрая «точка останова для бедных»: вставили ВызватьИсключение Строка(Сумма); и посмотрели значение;
  • 📦 код в транзакции, который должен откатиться целиком.

Перехват с подробностями выглядит так:

Попытка
    ЗагрузитьФайл(ИмяФайла);
Исключение
    Инфо = ИнформацияОбОшибке();
    ЗаписьЖурналаРегистрации("Обмен.Ошибка", УровеньЖурналаРегистрации.Ошибка, , ,
        ПодробноеПредставлениеОшибки(Инфо));
    ВызватьИсключение КраткоеПредставлениеОшибки(Инфо);
КонецПопытки;

Подробное представление со стеком вызовов уходит в журнал, а пользователю — короткий текст без строк модулей. Голое ВызватьИсключение; без текста внутри блока Исключение пробрасывает исходную ошибку дальше без изменений.

💡 В регламентном задании необработанное исключение тоже попадает в журнал регистрации, вместе со стеком. Поэтому иногда достаточно не глушить ошибки пустым Исключение КонецПопытки.

Возврат результата на клиент

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

&НаКлиенте
Процедура Проверить(Команда)
    Результат = ПроверитьНаСервере();
    Если Не Результат.Успех Тогда
        ПоказатьПредупреждение(, Результат.Текст);
    КонецЕсли;
КонецПроцедуры

&НаСервере
Функция ПроверитьНаСервере()
    Результат = Новый Структура("Успех, Текст", Истина, "");
    Если Объект.Товары.Количество() = 0 Тогда
        Результат.Успех = Ложь;
        Результат.Текст = "Табличная часть пуста";
    КонецЕсли;
    Возврат Результат;
КонецФункции

Плюсы такого подхода:

  • ✅ на клиенте доступны модальные и немодальные окна, которых нет на сервере;
  • ✅ серверная функция легко тестируется и вызывается из других мест;
  • ✅ в структуру можно сложить массив ошибок и показать их списком.

Ограничение одно: возвращать можно только сериализуемые значения. Структура, массив, строка, число, ссылка — да. ТаблицаЗначений на клиент не передаётся: преобразуйте её в массив структур или положите во временное хранилище через ПоместитьВоВременноеХранилище() и верните адрес.

Лог-файл на стороне сервера

Когда нужен длинный протокол — например, построчный разбор загрузки на 20 000 строк, — удобнее файл. Его можно открыть любым редактором и искать в нём по тексту.

ИмяЛога = КаталогВременныхФайлов() + "debug_obmen.log";
Лог = Новый ЗаписьТекста(ИмяЛога, КодировкаТекста.UTF8, , Истина);
Лог.ЗаписатьСтроку(СтрШаблон("%1 | %2 | %3",
    Формат(ТекущаяДатаСеанса(), "ДФ='dd.MM.yyyy HH:mm:ss'"),
    НомерСтроки, Артикул));
Лог.Закрыть();

Четвёртый параметр Истина — режим дополнения: каждая запись добавляется в конец, а не перезаписывает файл.

Что учесть:

  • 🖥 В клиент-серверном варианте файл появится на компьютере сервера 1С, а не у вас. Путь C:\Temp в коде — это диск сервера.
  • 🔐 Писать в каталог должна иметь право учётная запись службы агента сервера (по умолчанию USR1CV8). Нет прав — получите ошибку записи файла.
  • 👥 Если код выполняют несколько сеансов, они пишут в один файл одновременно. Добавляйте в имя файла номер сеанса или идентификатор, чтобы строки не перемешивались.
  • 🧹 КаталогВременныхФайлов() на сервере чистят. Для протокола, который нужен завтра, укажите постоянную папку.

Файловый вариант базы

В файловой базе серверный код выполняется в том же процессе, что и клиент. Поэтому лог-файл окажется на компьютере пользователя, который запустил операцию, а права на запись — права его учётной записи Windows. Код, который «работает у программиста» на файловой копии, после переноса в клиент-серверную базу может упасть с ошибкой доступа к каталогу. Проверяйте путь и права на той машине, где реально крутится рабочий процесс 1С.

Чтобы включать протокол без правки кода, заведите константу или параметр сеанса «Режим отладки» и пишите в файл только при включённом флаге. Тогда в рабочей базе вывод выключен, а при разборе проблемы его включают на час и отключают обратно.

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

Фоновые задания, отладчик и технологический журнал

Сообщения из фонового задания

Сообщения, сформированные в фоне через СообщениеПользователю, никуда не пропадают — они копятся в самом задании. Клиент забирает их так:

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

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

Отладчик вместо сообщений

Часто «вывести сообщение» хотят, потому что не работает остановка в серверном коде. В клиент-серверном варианте сервер отладки нужно разрешить: агент сервера запускается с ключом -debug в параметрах службы. Без него точки останова на сервере не срабатывают.

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

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

Технологический журнал

Для проблем, которые воспроизводятся только на рабочем сервере, есть технологический журнал платформы. Он настраивается файлом logcfg.xml в каталоге настроек сервера и пишет события: исключения (EXCP), долгие запросы, блокировки. Свой текст туда не выведешь, зато видно, где упал код, даже если программист ничего не логировал.

Какой способ выбрать

СпособКогда применятьГде читатьРиски
СообщениеПользователюСервер вызван из формыОкно сообщенийНе виден в регламентных заданиях и сервисах
Журнал регистрацииРегламентные задания, обмены, сервисыФорма журнала, отбор по событиюРазрастание журнала при записи в цикле
ВызватьИсключениеНужно прервать выполнениеОкно ошибки, журналОткатывает транзакцию, останавливает процесс
Возврат значенияФормы, проверки перед действиемКлиентский кодТолько сериализуемые типы
Лог-файлДлинный построчный протоколФайл на сервере 1СПрава, конкурентная запись, рост диска
Сообщения фонового заданияДлительные операцииКлиент опрашивает заданиеБез опроса сообщения не увидит никто

Короткое правило: в интерактивном коде — сообщение или возврат значения, в неинтерактивном — журнал регистрации, для разбора больших объёмов — файл.

Где выполняется код, из которого нужен вывод?

Ошибки при отладке серверного кода

  • ❌ Ищут лог-файл у себя на диске. В клиент-серверном варианте он на сервере 1С. Попросите администратора или пишите в общую сетевую папку, куда у службы есть права.
  • ❌ Ждут сообщения посреди долгой операции. До возврата на клиент их не будет. Для прогресса нужен фон и опрос задания.
  • ❌ Пишут в журнал транзакционно. При откате записи исчезают вместе с данными, и кажется, что код до этого места не дошёл.
  • ❌ Глушат ошибку пустым Исключение КонецПопытки. Код «работает», но молча ничего не делает. Минимум — запись ПодробноеПредставлениеОшибки() в журнал.
  • ❌ Склеивают числа со строкой без Формат. Сумма 1500000 превращается в 1 500 000 с неразрывными пробелами, и поиск по журналу перестаёт находить значение. Используйте Формат(Число, "ЧГ=0").
  • ❌ Забывают убрать отладочный вывод. Сотни записей «отладка 1», «отладка 2» в рабочем журнале мешают искать настоящие ошибки.

Частые вопросы

Почему Сообщить() в регламентном задании ничего не выводит?
У регламентного задания нет клиента и окна сообщений. Тексты теряются. Пишите в журнал регистрации через ЗаписьЖурналаРегистрации().
Можно ли из серверного кода показать вопрос «Да/Нет»?
Нет. Вопрос и предупреждение — клиентские методы. Верните с сервера признак, а вопрос задайте в клиентской процедуре и по ответу снова вызовите сервер.
Чем Сообщить() отличается от СообщениеПользователю?
Сообщить() — короткая форма, выводит только текст. Объект СообщениеПользователю позволяет привязать сообщение к полю формы и к ключу данных, поэтому в управляемом приложении предпочтительнее он.
Как замерить, сколько выполняется серверный участок кода?
Запомните ТекущаяУниверсальнаяДатаВМиллисекундах() до и после участка и запишите разницу в журнал регистрации. Для глубокого анализа используйте замер производительности в отладчике.
Нужны ли права, чтобы смотреть журнал регистрации?
Да, просмотр журнала доступен пользователям с соответствующим правом, обычно администраторам. Если у программиста его нет, записи увидит только администратор базы.