Как программно запустить обработку и выполнить её команду при начале работы системы в 1С 8.3?

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

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

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

Рассмотрим по шагам все варианты реализации: от быстрого исправления логики работы формы до профессионального переноса бизнес-кода и использования возможностей Библиотеки стандартных подсистем (БСП).

Выясняем причину: почему не работает простой вызов?

Типичная ошибка начинающего разработчика выглядит следующим образом. В модуле управляемого приложения в процедуре ПриНачалеРаботыСистемы пишется такой код:


Если ИмяПользователя() = "otpusk" Тогда
    Форма = ОткрытьФорму("Обработка.НЧ_ПредоставлениеОтпускаСотрудникам.Форма");
    // Пытаемся как-то вызвать команду...
    ЗавершитьРаботуСистемы(Ложь);
КонецЕсли;

Этот код принципиально неработоспособен по двум причинам:

  1. Асинхронность платформы 8.3: Метод ОткрытьФорму() на клиенте выполняется асинхронно. Платформа лишь инициирует процесс создания окна и сразу же переходит к следующей строке кода. В результате команда ЗавершитьРаботуСистемы(Ложь) отрабатывает мгновенно, закрывая сеанс еще до того, как форма обработки успеет фактически отрисоваться на экране и начать выполнение каких-либо внутренних процедур.
  2. Интерфейсный контекст: Попытка симулировать нажатие экранной кнопки или напрямую вызывать неэкспортные процедуры модуля формы из внешнего контекста приводит к ошибкам компиляции или выполнения.

Давайте разберем правильные варианты реализации этой задачи.

Решение 1. Архитектурный подход: Разделение интерфейса и бизнес-логики (Рекомендуемый способ)

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

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

Шаг 1. Перенос логики в модуль объекта обработки

Откроем конфигуратор, найдем нашу обработку и перейдем в её Модуль объекта. Опишем там экспортную процедуру, которая будет выполнять всю необходимую работу:


// В модуле объекта обработки
Процедура ВыполнитьАвтоматическуюОбработку(ПараметрыВыполнения) Экспорт
    
    // Переносим сюда всю логику, которая ранее выполнялась по кнопке
    ТабДок = Новый ТабличныйДокумент;
    СсылкаНаОбъект = ПараметрыВыполнения.ДатаСообщения;
    
    // Вызов внутренних серверных алгоритмов обработки
    СформироватьУведомленияНаСервере(ТабДок, СсылкаНаОбъект);
    
КонецПроцедуры

Шаг 2. Вызов из модуля управляемого приложения

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


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

Этот подход идеален, так как он полностью обходит проблему асинхронности клиентского интерфейса.

Решение 2. Интерактивный запуск через параметры формы и обработчик ожидания

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

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

Шаг 1. Передача параметра автозапуска при открытии формы

В модуле управляемого приложения мы инициируем открытие формы, передавая в нее специальный параметр Автозапуск:


// В Модуле управляемого приложения
Если НРег(ИмяПользователя()) = "otpusk" Тогда
    
    ПараметрыФормы = Новый Структура;
    ПараметрыФормы.Вставить("Автозапуск", Истина);
    
    ОткрытьФорму("Обработка.НЧ_ПредоставлениеОтпускаСотрудникам.Форма", ПараметрыФормы);
    
КонецЕсли;

Обратите внимание: мы не пишем здесь ЗавершитьРаботуСистемы. Завершением работы будет управлять сама открытая форма после того, как выполнит свою задачу.

Шаг 2. Обработка параметра в модуле формы

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


&НаКлиенте
Процедура ПриОткрытии(Отказ)
    
    // Проверяем, пришел ли параметр автоматического выполнения
    Если Параметры.Свойство("Автозапуск") И Параметры.Автозапуск Тогда
        // Подключаем однократный обработчик ожидания через 0.1 секунды
        ПодключитьОбработчикОжидания("ВыполнитьАлгоритмИЗакрытьСеанс", 0.1, Истина);
    КонецЕсли;
    
КонецПроцедуры

Шаг 3. Реализация процедуры выполнения и закрытия

Определим процедуру, которая вызовется таймером. Она выполнит клиентскую команду и затем инициирует закрытие программы:


&НаКлиенте
Процедура ВыполнитьАлгоритмИЗакрытьСеанс()
    
    // Вызываем процедуру выполнения основной команды (она должна быть Экспортной)
    Команда1(Неопределено);
    
    // По окончании работы закрываем сеанс программы
    ЗавершитьРаботуСистемы(Ложь);
    
КонецПроцедуры

&НаКлиенте
Процедура Команда1(Команда) Экспорт
    
    ТабДок = Новый ТабличныйДокумент;
    СсылкаНаОбъект = Объект.ДатаСообщ;
    
    // Выполняем основное действие на сервере
    Команда1НаСервере(ТабДок, СсылкаНаОбъект);
    
КонецПроцедуры

Благодаря использованию метода ПодключитьОбработчикОжидания(), форма успевает полностью инициализироваться в операционной системе, корректно отрабатывает весь клиент-серверный цикл транзакций, и только после этого приложение штатно закрывается.

Решение 3. Работа с внешними обработками (.epf) и учет безопасного режима

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

Проанализируем пример кода для программного запуска внешней обработки:


ИмяФайла = "C:\ExternalProcessings\SendOtpuska.epf";

// Создаем объект внешней обработки. 
// Обратите внимание на параметры: второй и третий параметры отвечают за безопасный режим.
// Если вашей обработке требуется доступ к сети (отправка писем) или дисковой системе, 
// безопасный режим необходимо отключить (передать Ложь).
ВнешнийОбъект = ВнешниеОбработки.Создать(ИмяФайла, Ложь, Ложь);

// Вызываем экспортный метод, написанный в модуле объекта внешней обработки
ПараметрыЗапуска = Новый Структура("ДатаСообщения", ТекущаяДата());
ВнешнийОбъект.ВыполнитьАвтоматическуюОбработку(ПараметрыЗапуска);

Важное предупреждение: Использование жестко прописанных путей к файлам вроде "C:\ExternalProcessings\..." крайне не рекомендуется в современных реалиях клиент-серверных архитектур. Этот файл должен физически существовать на компьютере, где выполняется код (на клиенте или на сервере, в зависимости от контекста выполнения вызова).

Решение 4. Использование механизмов БСП (для ЗУП 3.1)

Поскольку в условиях задачи упоминается конфигурация «ЗУП 3.1», разработанная на базе БСП (Библиотеки стандартных подсистем), лучшим решением будет полный отказ от написания кастомного кода в модуле управляемого приложения.

Вместо изменения кода конфигурации воспользуемся подсистемой «Дополнительные отчеты и обработки»:

  1. Добавим в модуль объекта внешней обработки стандартные экспортные функции интеграции с БСП (функция СведенияОВнешнейОбработке()).
  2. Зададим режим запуска для команды обработки: ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыВызовСерверногоМетода(). Это позволит выполнять код обработки вообще без открытия интерактивных окон.
  3. Зарегистрируем обработку в базе данных через пользовательский интерфейс (раздел «Администрирование» — «Печатные формы, отчеты и обработки»).
  4. Настроим штатное расписание выполнения этой команды. Система сама в фоновом режиме на сервере будет запускать выполнение логики по заданному графику. Нам больше не потребуется создавать отдельного пользователя в базе, держать открытым его сеанс и программно закрывать его.

Использование механизмов БСП гарантирует стабильность работы решения при обновлениях конфигурации и существенно повышает общую безопасность и производительность информационной системы.

← На главную