Как запустить регламентное задание из кода 1С 8.3: сразу, по расписанию и извне
Содержание
Метода «выполнить сейчас» у объекта РегламентноеЗадание в 1С 8.3 нет. Программно регламентное задание запускают двумя путями: включают его и задают расписание через менеджер РегламентныеЗадания (тогда задание стартует планировщик кластера), либо сразу вызывают тот же метод фоновым заданием через ФоновыеЗадания.Выполнить(Задание.Метаданные.ИмяМетода, Задание.Параметры, ...). Так же работают кнопка «Выполнить сейчас» в типовых конфигурациях и обработка «Консоль заданий».
Типичная ситуация: ночная выгрузка остатков упала, склад ждёт данные к 9:00, а следующий запуск по расписанию только завтра. Ниже код для каждого способа, передача параметров, вызов извне через HTTP и COM и разбор, почему задание не стартует.
Что должно быть готово до запуска
Регламентное задание — это объект метаданных, который ссылается на процедуру. Без правильной процедуры никакой код запуска не поможет.
Проверьте в конфигураторе четыре вещи:
- 📌 Имя метода. В свойствах задания указана экспортная процедура общего модуля. Модуль должен иметь флаг «Сервер». Клиентский модуль или неэкспортная процедура дадут ошибку при старте.
- 📌 Сигнатура процедуры. Число параметров процедуры совпадает с числом элементов массива
Параметры. Удобно делать параметры необязательными:Процедура ВыгрузкаОстатков(Склад = Неопределено) Экспорт. - 📌 Флаг «Предопределённое». Предопределённое задание существует в базе в одном экземпляре, его находят через
НайтиПредопределенное(). Несколько экземпляров с разными параметрами создают только у задания со снятым флагом. - 📌 Режим базы. В клиент-серверном варианте задания запускает планировщик кластера. В файловой базе задания выполняются только при открытом сеансе клиента.
Для файловой базы можно держать отдельный сеанс под служебным пользователем, запущенный с ключом /AllowExecuteScheduledJobs -Force. Тогда задания выполняются в нём, а не в сеансе случайного бухгалтера.
Работа с объектами РегламентноеЗадание (поиск, запись, удаление) требует административных прав. Обычному пользователю код упадёт с нарушением прав доступа. Для запуска фонового задания такие права не нужны.
Как создать и включить регламентное задание кодом
Объекта «Планировщик регламентных заданий» во встроенном языке нет. Всё делается через менеджер РегламентныеЗадания, а расписание описывает объект РасписаниеРегламентногоЗадания.
Включить предопределённое задание и задать расписание
Код выполняется на сервере:
&НаСервереБезКонтекста
Процедура ВключитьВыгрузкуОстатков()
Задание = РегламентныеЗадания.НайтиПредопределенное(
Метаданные.РегламентныеЗадания.ВыгрузкаОстатков);
Расписание = Новый РасписаниеРегламентногоЗадания;
Расписание.ПериодПовтораДней = 1; // каждый день
Расписание.ПериодПовтораВТечениеДня = 3600; // раз в час, в секундах
Расписание.ВремяНачала = Дата(1, 1, 1, 7, 0, 0);
Расписание.ВремяКонца = Дата(1, 1, 1, 21, 0, 0);
Задание.Расписание = Расписание;
Задание.Использование = Истина;
Задание.Записать();
КонецПроцедуры
Задание будет запускаться каждый час с 7:00 до 21:00. Если нужно «только по будням», заполните Расписание.ДниНедели массивом чисел от 1 до 5 (1 — понедельник).
Создать отдельный экземпляр с параметрами
Пример: одна процедура выгрузки, но по каждому складу своё задание и своё время.
Задание = РегламентныеЗадания.СоздатьРегламентноеЗадание(
Метаданные.РегламентныеЗадания.ВыгрузкаОстатков);
Задание.Наименование = "Выгрузка остатков: склад Север";
Задание.Ключ = "Склад_Север";
Параметры = Новый Массив;
Параметры.Добавить(СкладСевер); // ссылка на элемент справочника
Задание.Параметры = Параметры;
Задание.ИмяПользователя = "Робот_Обмен";
Задание.Расписание = Расписание; // объект из примера выше
Задание.Использование = Истина;
Задание.Записать();
Найти такие экземпляры потом можно отбором:
Отбор = Новый Структура("Метаданные, Ключ",
Метаданные.РегламентныеЗадания.ВыгрузкаОстатков, "Склад_Север");
Найденные = РегламентныеЗадания.ПолучитьРегламентныеЗадания(Отбор);
Расписание и флаг использования хранятся в данных базы, а не в конфигурации. Менять их кодом можно в рабочей базе без монопольного режима и без обновления конфигурации.
В типовых конфигурациях на БСП
В Бухгалтерии 3.0, ЗУП 3.1, УТ 11 прямой вызов РегламентныеЗадания работает, но удобнее программный интерфейс библиотеки: модуль РегламентныеЗаданияСервер с функциями НайтиЗадания, ИзменитьЗадание, ДобавитьЗадание, УстановитьИспользованиеРегламентногоЗадания. Он учитывает режим работы в модели сервиса, где задания живут в очереди, а не в кластере.
Немедленный запуск регламентного задания программно
Чтобы выполнить задание прямо сейчас, не дожидаясь расписания, берут его метод и параметры и запускают фоновое задание. Этот приём главный, ради него обычно и ищут тему.
&НаСервере
Функция ЗапуститьЗаданиеСейчас(ИмяЗадания) Экспорт
Задание = РегламентныеЗадания.НайтиПредопределенное(
Метаданные.РегламентныеЗадания[ИмяЗадания]);
Ключ = Строка(Задание.УникальныйИдентификатор);
// Не запускаем второй экземпляр, если первый ещё работает
Отбор = Новый Структура("Ключ, Состояние",
Ключ, СостояниеФоновогоЗадания.Активно);
Если ФоновыеЗадания.ПолучитьФоновыеЗадания(Отбор).Количество() > 0 Тогда
ВызватьИсключение "Задание уже выполняется";
КонецЕсли;
Фоновое = ФоновыеЗадания.Выполнить(
Задание.Метаданные.ИмяМетода,
Задание.Параметры,
Ключ,
Задание.Наименование + " (ручной запуск)");
Возврат Фоновое.УникальныйИдентификатор;
КонецФункции
Что здесь происходит:
- По имени объекта метаданных находим задание в базе.
- В качестве ключа берём его уникальный идентификатор. Платформа не даст запустить два активных фоновых задания с одинаковым ключом и методом.
- Проверяем, нет ли активного запуска, и выдаём понятное сообщение вместо системной ошибки.
- Запускаем фоновое задание с тем же методом и параметрами и возвращаем его идентификатор, чтобы потом проверить статус.
Фоновое задание, запущенное так, не привязано к регламентному. У него пустое свойство РегламентноеЗадание, и Задание.ПоследнееЗадание после ручного запуска не обновится. Ищите ручные запуски по ключу или по идентификатору, а не отбором по регламентному заданию.
Для непредопределённого экземпляра замените поиск на РегламентныеЗадания.НайтиПоУникальномуИдентификатору(УИД) или на отбор по ключу из предыдущего раздела.
Если нужно, чтобы ручной запуск отработал под тем же пользователем, что и по расписанию, учтите: фоновое задание выполняется от имени того, кто его запустил. Права и записи в журнале регистрации будут от текущего пользователя.
Параметры, ключ и пользователь: контекст выполнения
Регламентное задание выполняется на сервере в отдельном сеансе. Там нет форм, текущего клиента и значений, которые пользователь держал в памяти. Всё, что нужно процедуре, передают параметрами или читают из базы.
| Свойство | Что задаёт | На что влияет |
|---|---|---|
Параметры | Массив значений для процедуры | Порядок элементов = порядок параметров процедуры |
Ключ | Строка-идентификатор экземпляра | Не даёт запустить два одинаковых задания параллельно |
ИмяПользователя | Пользователь базы | Права, ПользователиИнформационнойБазы.ТекущийПользователь(), журнал регистрации |
Наименование | Текст для списка заданий | Только отображение |
КоличествоПовторовПриАварийномЗавершении | Число повторов | Сколько раз платформа перезапустит упавшее задание |
ИнтервалПовтораПриАварийномЗавершении | Пауза в секундах | Через сколько повторять |
Практические правила по параметрам:
- ✅ Передавайте простые значения и ссылки: строки, числа, даты, ссылки на справочники и документы.
- ❌ Не передавайте объекты, таблицы значений с формы и данные формы. Их состояние в момент выполнения непредсказуемо.
- ✅ Большой набор настроек храните в регистре сведений или константе, а в параметр кладите только ключ записи.
- ✅ Задавайте
ИмяПользователяявно. Служебный пользователь с нужной ролью проще в аудите, чем запуск «от имени никого».
Если поменять число параметров процедуры, а у созданных экземпляров оставить старый массив Параметры, задания начнут падать при старте. После изменения сигнатуры пройдитесь по экземплярам и перезапишите параметры.
Запуск регламентного задания извне: HTTP-сервис и COM
Иногда стартовать задание должна внешняя система: сайт, шина, скрипт администратора. Прямого вызова регламентного задания снаружи нет, поэтому делают серверную точку входа, которая запускает фоновое задание.
Через HTTP-сервис
Создайте HTTP-сервис с шаблоном URL /jobs/{job} и методом POST. Обработчик:
Функция ЗапускPOST(Запрос)
Разрешённые = СтрРазделить("ВыгрузкаОстатков,ЗагрузкаКурсов", ",");
ИмяЗадания = Запрос.ПараметрыURL["job"];
Если Разрешённые.Найти(ИмяЗадания) = Неопределено Тогда
Возврат Новый HTTPСервисОтвет(404);
КонецЕсли;
УстановитьПривилегированныйРежим(Истина);
Задание = РегламентныеЗадания.НайтиПредопределенное(
Метаданные.РегламентныеЗадания[ИмяЗадания]);
Фоновое = ФоновыеЗадания.Выполнить(Задание.Метаданные.ИмяМетода,
Задание.Параметры, Строка(Задание.УникальныйИдентификатор));
Ответ = Новый HTTPСервисОтвет(202);
Ответ.Заголовки.Вставить("Content-Type", "application/json");
Ответ.УстановитьТелоИзСтроки(СтрШаблон("{""id"":""%1""}",
Строка(Фоновое.УникальныйИдентификатор)));
Возврат Ответ;
КонецФункции
Ключевые моменты:
- 🔒 Белый список имён. Никогда не принимайте имя задания или метода из запроса без проверки. Иначе снаружи можно вызвать любую экспортную серверную процедуру.
- 🔒 Привилегированный режим нужен, потому что пользователю публикации обычно не дают административных прав. Включайте его только на время поиска и запуска.
- ⏱ Код 202 и идентификатор. HTTP-запрос не ждёт окончания задания. Внешняя система получает
idи опрашивает статус вторым методом GET.
Повторный POST во время работы задания вызовет исключение из-за занятого ключа. Оберните запуск в Попытка, чтобы вернуть код 409 вместо 500.
Через COM-соединение
Из Windows-скрипта на машине с установленной платформой подключаются через V83.COMConnector. Компонента регистрируется командой regsvr32 comcntr.dll из папки bin платформы; разрядность скрипта должна совпадать с разрядностью зарегистрированной компоненты.
В конфигурации нужен общий модуль с флагами «Сервер» и «Внешнее соединение». Модуль и функцию удобно назвать латиницей, чтобы не мучиться с кодировкой в скриптах, например JobsExternal.Start(ИмяЗадания). Внутри — тот же код, что в разделе про немедленный запуск.
$connector = New-Object -ComObject V83.COMConnector
$base = $connector.Connect('Srvr="srv1c";Ref="buh";Usr="robot";Pwd="***";')
$id = $base.JobsExternal.Start("ВыгрузкаОстатков")
Write-Output $id
Пароль в открытом виде в скрипте — риск. Храните его в защищённом хранилище учётных данных Windows и давайте пользователю robot только роль для запуска заданий.
Третий вариант для простых случаев — запуск клиента 1cv8.exe ENTERPRISE с ключом /Execute и внешней обработкой из планировщика Windows. Он тяжелее: поднимается целый клиентский сеанс и занимает лицензию.
Какой способ запуска выбрать
| Способ | Когда подходит | Ограничения |
|---|---|---|
| Включить задание и задать расписание | Регулярная работа: обмены, загрузка курсов, закрытие дня | Старт по расписанию, не мгновенно; в файловой базе нужен открытый сеанс |
ФоновыеЗадания.Выполнить с методом задания | Разовый запуск «сейчас» из формы или кода | Не обновляет ПоследнееЗадание, выполняется от текущего пользователя |
| HTTP-сервис | Запуск из сайта, шины, другой системы | Нужна публикация на веб-сервере и защита точки входа |
| COM-соединение | Скрипты администратора внутри сети | Только Windows, нужна установленная платформа той же версии |
1cv8.exe /Execute | Нет доступа к правке конфигурации | Полноценный сеанс, лицензия, медленный старт |
Для большинства задач хватает пары «расписание + кнопка немедленного запуска на фоновом задании». Внешние способы нужны, когда инициатор запуска — не человек в 1С.
Контроль выполнения: статус, ошибки, отмена
Запустить мало: нужно знать, чем закончилось. Фоновое задание находят по идентификатору и смотрят состояние.
Функция СтатусЗадания(УИДСтрокой) Экспорт
Фоновое = ФоновыеЗадания.НайтиПоУникальномуИдентификатору(
Новый УникальныйИдентификатор(УИДСтрокой));
Если Фоновое = Неопределено Тогда
Возврат "не найдено";
ИначеЕсли Фоновое.Состояние = СостояниеФоновогоЗадания.Активно Тогда
Возврат "выполняется с " + Формат(Фоновое.Начало, "ДФ=HH:mm");
ИначеЕсли Фоновое.Состояние = СостояниеФоновогоЗадания.ЗавершеноАварийно Тогда
Возврат ПодробноеПредставлениеОшибки(Фоновое.ИнформацияОбОшибке);
Иначе
Возврат Строка(Фоновое.Состояние);
КонецЕсли;
КонецФункции
Для запусков по расписанию то же самое берут из Задание.ПоследнееЗадание: если задание ещё ни разу не выполнялось, там Неопределено.
Что ещё пригодится:
- ⏳
Фоновое.ОжидатьЗавершенияВыполнения(30)— подождать до 30 секунд. Удобно в тестах, но не в обработчике HTTP-запроса. - ✋
Фоновое.Отменить()— попросить задание остановиться. Длинную процедуру стоит писать так, чтобы она работала порциями и фиксировала прогресс. - 💬
Фоновое.ПолучитьСообщенияПользователю()— забрать то, что процедура выводила черезСообщить(). - 📜 Журнал регистрации с отбором по событиям фоновых заданий — история запусков, ошибок и отмен, в том числе по расписанию.
В типовых конфигурациях список, расписание и ручной запуск собраны в Администрирование → Обслуживание → Регламентные операции → Регламентные и фоновые задания.
Почему регламентное задание не стартует
Большинство «не работает » сводится к нескольким причинам. Проверяйте их по порядку, от простого к сложному.
Снимать блокировку регламентных заданий на копии рабочей базы опасно: копия начнёт отправлять те же обмены, письма и выгрузки, что и боевая. Сначала отключите задания, которые ходят во внешние системы.
Если задание стартует, но падает, ответ почти всегда в ИнформацияОбОшибке последнего запуска или в журнале регистрации. Ещё одна частая причина — процедура обращается к тому, что есть только на клиенте: формам, диалогам, локальным файлам пользователя.