Почему не видна процедура обработки при вызове из регламентного задания в УТ 10.3?

Программист 1С v8.3 (Обычные формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

При автоматизации типовых конфигураций на обычных формах (в частности, 1С:Управление торговлей 10.3) разработчики часто сталкиваются с ситуацией: внешняя или встроенная обработка отлично работает при ручном запуске пользователем через главное меню Файл - Открыть, но при попытке вызвать ее из регламентного задания система выдает ошибку «Метод объекта не обнаружен» или сообщает, что вызываемая процедура не определена.

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

Причины возникновения ошибки: конфликт клиентского и серверного контекстов

Проанализируем архитектуру выполнения кода, чтобы понять корень проблемы:

  1. Разделение контекстов «Клиент – Сервер». Фоновое задание, привязанное к регламентному заданию, всегда выполняется исключительно на сервере 1С:Предприятия в неинтерактивной сессии. В то же время типовой интерактивный запуск происходит в толстом клиенте. Серверный код физически не имеет доступа к клиентскому окружению: из серверного контекста невозможно вызвать процедуры клиентских модулей.
  2. Недоступность модуля обычного приложения. МодульОбычногоПриложения компилируется только на стороне клиента. Если обработка обращается к процедурам, функциям или глобальным переменным этого модуля (например, к переменной глТекущийПользователь), серверное регламентное задание падает с ошибкой, так как этих методов в его пространстве имен просто не существует.
  3. Инструкции препроцессора в модуле обработки. Часто в модулях обработок процедуры обрамляются директивами:
    
    #Если Клиент Тогда
    Процедура МояПроцедура() Экспорт
        // Код процедуры
    КонецПроцедуры
    #КонецЕсли
    
    Если экспортный метод находится внутри блока #Если Клиент Тогда, то при создании объекта обработки на сервере через Обработки.МояОбработка.Создать() данный метод вообще не компилируется. Экземпляр объекта успешно создается, но платформа сообщает: «Метод объекта не обнаружен».
  4. Интерактивные функции интерфейса. Если убрать директиву #Если Клиент Тогда, компилятор на сервере начнет проверять содержимое метода. Если в теле процедуры встречаются команды вроде Предупреждение(), Вопрос(), ОткрытьФорму() или работа с объектами торгового оборудования, регламентное задание завершится аварийно, так как интерфейсные методы на сервере запрещены.
  5. Неинициализированные параметры сеанса. В обычных формах права, константы и параметры пользователя инициализируются при старте толстого клиента. В фоновом задании инициализация сеанса происходит по усеченной схеме, из-за чего стандартные проверки прав или обращения к ПараметрыСеанса.ТекущийПользователь вызывают исключения.

Способ 1. Разделение бизнес-логики и изоляция интерактивных вызовов

Рассмотрим основной способ исправления кода обработки. Необходимо сделать так, чтобы метод компилировался на сервере, но не вызывал интерактивных окон диалога.

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


Процедура ВыполнитьДействие() Экспорт

    // Выполняем основную серверную логику обработки данных
    ВыполнитьОбработкуДанных();

    #Если Клиент Тогда
        // Интерактивное оповещение пользователя при ручном запуске
        ПоказатьОповещениеПользователя("Обработка завершена успешно!");
    #Иначе
        // При выполнении в регламентном задании пишем событие в журнал
        ЗаписьЖурналаРегистрации(
            "РегламентнаяОбработка",
            УровеньЖурналаРегистрации.Информация,
            Метаданные.Обработки.МояОбработка,
            ,
            "Обработка успешно выполнена регламентным заданием."
        );
    #КонецЕсли

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

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

Способ 2. Вынос общих функций в серверный модуль

Если процедура, которая нужна обработке, находится в МодулеОбычногоПриложения, вызывать ее напрямую из регламентного задания нельзя. Разберем правильный перенос логики:

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

// В общем модуле РегламентныеЗаданияСервер:
Процедура ОбщаяЛогика() Экспорт
    // Код, приспособленный для работы на стороне сервера
КонецПроцедуры

Теперь эту процедуру можно без ошибок вызывать как из модуля обработки в контексте регламентного задания, так и при интерактивной работе пользователя.

Способ 3. Перенос методов в модуль менеджера обработки

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


// В модуле менеджера обработки МояОбработка:
Процедура ВыполнитьАлгоритм() Экспорт
    // Серверная логика обработки данных
КонецПроцедуры

// В процедуре регламентного задания общего модуля:
Процедура ВыполнитьЗадание() Экспорт
    // Вызываем процедуру напрямую без создания объекта в памяти
    Обработки.МояОбработка.ВыполнитьАлгоритм();
КонецПроцедуры

Способ 4. Инициализация параметров сеанса перед вызовом обработки

Если серверный алгоритм обращается к типовым механизмам УТ 10.3, которые требуют установленного пользователя, инициализируем параметры сеанса вручную перед запуском алгоритма обработки:


Процедура ВыполнитьЗадание() Экспорт

    // Проверяем заполненность текущего пользователя в сеансе
    Если Не ЗначениеЗаполнено(ПараметрыСеанса.ТекущийПользователь) Тогда
        СлужебныйПользователь = Справочники.Пользователи.НайтиПоНаименованию("РегламентныйПользователь");
        ПараметрыСеанса.ТекущийПользователь = СлужебныйПользователь;
    КонецЕсли;

    // Вызываем целевую обработку
    Обр = Обработки.МояОбработка.Создать();
    Обр.ВыполнитьДействие();

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

Альтернативный вариант: Запуск отдельного сеанса толстого клиента

В ситуациях, когда обработка слишком тесно интегрирована с клиентскими механизмами и переписывание кода под сервер нецелесообразно по времени, применяют запуск полноценного сеанса толстого клиента через планировщик операционной системы:

  1. На сервере или выделенной рабочей станции создается задача в Планировщике заданий Windows.
  2. Запуск 1С выполняется в пакетном режиме с ключом запуска обработки:
    
    "C:\Program Files\1cv8\common\1cestart.exe" ENTERPRISE /S "server-1c\trade" /N "Робот" /P "Пароль" /Execute "C:\Scripts\RunTask.epf"
    
  3. Во внешней обработке запуска в обработчике события ПриОткрытии() обязательно прописывают безусловное завершение работы, чтобы процесс не оставался висеть в памяти:

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

    // Обязательно закрываем клиентский сеанс
    ЗавершитьРаботуСистемы(Ложь);
КонецПроцедуры

При таком подходе сеанс запускается как полноценный толстый клиент: МодульОбычногоПриложения отрабатывает полностью, глобальные переменные инициализируются, а директивы #Если Клиент Тогда остаются активными.

← На главную