При администрировании и разработке крупных систем на платформе 1С:Предприятие 8.3 часто возникает классическая задача: как запустить ресурсоемкую регламентную процедуру (например, восстановление последовательности документов) в монопольном или привилегированном режиме, и при этом временно отключить некоторые «тяжелые» бизнес-проверки.
В обычных условиях при проведении документов система должна жестко контролировать остатки товаров, взаиморасчеты и кредитные лимиты контрагентов. Однако при групповом перепроведении исторических данных за прошлые периоды такие проверки не только избыточны, но и вредны, так как они могут заблокировать проведение старых документов из-за изменившихся лимитов. В этой статье мы подробно разберем, как научить систему понимать, что идет регламентное массовое проведение, и рассмотрим различные программные методы решения этой задачи — от низкоуровневого чтения параметров командной строки до элегантных архитектурных подходов самой платформы 1С.
Выясним причину, почему стандартными средствами встроенного языка 1С нельзя получить строку запуска, содержащую ключ /UC. Этот ключ используется менеджером кластера исключительно на этапе авторизации для обхода блокировки информационной базы и физически не передается внутрь сеанса пользователя. Тем не менее, если клиентское приложение работает под управлением операционной системы Windows, мы можем прибегнуть к системному обходному пути.
Проанализируем ситуацию: операционная система хранит полную командную строку каждого запущенного процесса. Мы можем обратиться к инструментарию управления Windows (WMI) и вытащить данные процесса нашего клиента 1С. Рассмотрим следующий пример кода, который считывает параметры запуска:
// Подключаемся к локальной службе WMI операционной системы
Локатор = Новый COMОбъект("WbemScripting.SWbemLocator");
СлужбаWMI = Локатор.ConnectServer(".");
// Делаем запрос к запущенным процессам тонкого, толстого клиента или конфигуратора
ЗапросWMI = "SELECT ProcessId, CommandLine FROM Win32_Process WHERE Name LIKE '1cv8%'";
РезультатЗапроса = СлужбаWMI.ExecQuery(ЗапросWMI);
Для Каждого Процесс Из РезультатЗапроса Цикл
СтрокаЗапуска = Процесс.CommandLine;
// Проверим наличие ключевого слова блокировки в командной строке
Если Найти(СтрокаЗапуска, "/UC") > 0 Тогда
// Здесь мы можем распарсить строку и извлечь секретный код разблокировки
// Например, использовать его для подтверждения того, что сеанс административный
Прервать;
КонецЕсли;
КонецЦикла;
Важное предупреждение: этот метод имеет ряд существенных недостатков. Во-первых, он привязан к операционной системе Windows и не будет работать на серверах под управлением Linux или на мобильных клиентах. Во-вторых, если на одном компьютере запущено несколько сеансов 1С, вам придется дополнительно определять PID текущего процесса, чтобы сопоставить его со своим сеансом. Использовать WMI рекомендуется только в крайних случаях, когда другие методы категорически не подходят.
Перейдем к более изящным решениям. Платформа 1С предоставляет официальный и кроссплатформенный механизм передачи пользовательских параметров при старте системы через ключ командной строки /C. Все, что передается после этого ключа, доступно в коде через глобальную переменную ПараметрыЗапуска.
Рассмотрим по шагам, как настроить этот процесс:
"C:\Program Files\1cv8\8.3.XX.XXXX\bin\1cv8.exe" ENTERPRISE /F"D:\Bases\Trade" /N"Robot" /P"Pass" /C"РежимМассовогоПерепроведения"
ОбработкаПроведения) добавим проверку значения глобального параметра:
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
// Если система запущена с флагом массовой обработки, пропускаем контроль лимитов
Если ПараметрыЗапуска <> "РежимМассовогоПерепроведения" Тогда
// Выполняем стандартную проверку кредитной линии контрагента
ПроверитьКредитныйЛимит(ЭтотОбъект, Отказ);
КонецЕсли;
КонецПроцедуры
Этот способ полностью безопасен, работает на любых операционных системах и не требует использования низкоуровневых системных библиотек. Параметр ПараметрыЗапуска доступен как в толстом, так и в тонком клиенте при старте системы.
Проанализируем профессиональный стандарт разработки, заложенный создателями платформы 1С. Для отключения транзакционных проверок при записи и проведении объектов в системе существует стандартное свойство ОбменДанными.Загрузка. Изначально оно предназначалось для того, чтобы документы, загружаемые из других баз, записывались "как есть", даже если они нарушают текущие бизнес-правила (ведь в исходной базе они уже были проведены и проверены).
Мы можем использовать этот флаг при написании собственной обработки для восстановления последовательностей. Посмотрим на пример кода такой обработки:
ВыборкаДокументов = Документы.РеализацияТоваровУслуг.Выбрать(НачалоПериода, КонецПериода);
Пока ВыборкаДокументов.Следующий() Цикл
ДокументОбъект = ВыборкаДокументов.ПолучитьОбъект();
// Включаем режим загрузки, чтобы отключить прикладные проверки в модулях
ДокументОбъект.ОбменДанными.Загрузка = Истина;
Попытка
ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение);
Исключение
ЗаписьЖурналаРегистрации("ВосстановлениеПоследовательности",
УровеньЖурналаРегистрации.Ошибка, , ,
"Ошибка проведения документа: " + ДокументОбъект);
КонецПопытки;
КонецЦикла;
Теперь разберем, как должна выглядеть обработка этого признака внутри самого документа. В модуле объекта (например, в процедуре ПередЗаписью или ОбработкаПроведения) мы делаем проверку свойства ОбменДанными.Загрузка:
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
// Если документ проводится в режиме загрузки данных (восстановления),
// то интерактивные проверки кредитной линии не выполняются
Если Не ОбменДанными.Загрузка Тогда
// Проверяем долги покупателя
ПроверитьВзаиморасчетыСПокупателем(Отказ);
КонецЕсли;
КонецПроцедуры
Этот подход считается наиболее правильным с точки зрения архитектуры 1С. Он позволяет обойтись без привязки к параметрам командной строки и гарантирует корректную работу алгоритмов перепроведения как при запуске вручную, так и через фоновые задания.
Рассмотрим ситуацию, когда массовое перепроведение запускается автоматически на сервере с помощью стандартного механизма регламентных заданий 1С. В этом случае нам не нужно передавать никаких параметров командной строки. Серверная часть конфигурации может самостоятельно определить тип текущего сеанса.
Давайте посмотрим на пример реализации такой проверки непосредственно в коде модуля документа:
ТекущийСеанс = ПолучитьТекущийСеансИнформационнойБазы();
// Проверяем, запущено ли выполнение в фоновом режиме (роботом по расписанию)
Если ТекущийСеанс.ИмяПриложения = "BackgroundJob" Тогда
// Это регламентное или фоновое задание.
// Пропускаем контроль задолженности контрагента, так как перепроведение идет в автоматическом режиме
Иначе
// Обычный сеанс пользователя (ТонкийКлиент, ТолстыйКлиент или ВебКлиент)
ВыполнитьЖесткуюПроверкуЛимитов();
КонецЕсли;
Этот способ позволяет полностью автоматизировать логику выполнения без необходимости настройки ярлыков запуска или планировщика задач операционной системы. Все настройки расписания и запуска регламентных процедур администрируются непосредственно внутри базы данных 1С.
Мы подробно разобрали несколько способов решения проблемы контроля данных при групповой обработке документов. Подведем итоги работы:
/UC напрямую — это трудоемкий путь, требующий обращения к низкоуровневым системным функциям ОС (WMI). Его стоит избегать для сохранения кроссплатформенности конфигурации./C и системное свойство ПараметрыЗапуска.ОбменДанными.Загрузка = Истина в теле обработок проведения и анализируйте его в модулях документов.BackgroundJob.