Рассмотрим частую и довольно коварную ситуацию, с которой сталкиваются разработчики 1С при создании обработок для обмена данными. Суть проблемы заключается в следующем: при ручном запуске обработки выгрузка товаров (например, на сайт) проходит успешно. Однако, как только эта же обработка запускается автоматически через регламентное задание, система выдает ошибку:
Параметр с указанным именем не найден
В тексте ошибки обычно фигурирует строка с вызовом метода установки параметра, например:
КомпоновщикТоваров.Настройки.ПараметрыДанных.УстановитьЗначениеПараметра("ВыгружатьТолькоИзменения", ВыгружатьТолькоИзменения);
Проанализируем эту ситуацию подробно, разберем причины такого поведения платформы и выясним, как правильно решить данную проблему.
Разберем по шагам, чем отличается выполнение кода в сеансе пользователя от серверного сеанса фонового задания. Это классическая проблема разрыва контекста.
При отладке можно заметить странные аномалии. Например, если в ручном режиме параметров в компоновщике пять (ИспользоватьХарактеристики, КатегорияЦены1, ВыгружатьТолькоИзменения и т.д.), то при запуске регламентного задания после попытки загрузить настройки из XML количество параметров может сократиться до одного.
Еще один интересный симптом: вместо ожидаемого булевого значения параметра (например, Ложь) в фоновом задании туда может записываться пустая дата (01.01.0001 00:00:00). Посмотрим на основные причины, почему это происходит.
Для того чтобы объект КомпоновщикНастроек понимал, какие параметры в нем существуют и какие у них типы, он должен быть жестко связан со схемой компоновки данных (СКД).
Когда вы открываете форму обработки интерактивно, платформа 1С часто берет инициализацию на себя, связывая основную схему с компоновщиком формы. В регламентном задании код выполняется на сервере, формы нет, и объект создается программно. Компоновщик может оказаться «пустым».
Решение: Перед тем как десериализовать настройки или устанавливать параметры, принудительно инициализируйте компоновщик, передав ему схему.
КомпоновщикТоваров.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(СхемаКомпоновкиДанных));
Часто настройки сохраняются в формате XML, а затем восстанавливаются с помощью методов десериализации или сериализатора XDTO. Вспомним, что регламентные задания выполняются от имени системного пользователя (или специально созданного служебного пользователя, «робота»).
Рассмотрим фрагмент XML-настроек:
<Property name="КатегорияЦеныРозница">
<Value xmlns:d3p1="..." xsi:type="d3p1:CatalogRef.ВидыЦен">f24a09fc-601b-11e8-bea2-80a589b79c18</Value>
</Property>
Если у пользователя, под которым запускается регламентное задание, нет прав на чтение справочника ВидыЦен, сериализатор не сможет преобразовать этот узел в ссылку. В результате загрузка прерывается, коллекция параметров повреждается, и вместо пяти параметров загружается только один.
Решение: Проверьте права пользователя, под которым работает регламентное задание. Убедитесь, что ему доступны все объекты метаданных, ссылки на которые хранятся в сохраненных настройках СКД.
Выясним причину появления значения 01.01.0001 вместо логического Ложь. В СКД для параметров задаются «Доступные типы».
Если при загрузке настроек из-за ошибок (например, нехватки прав или сдвига индексов в поврежденной коллекции) тип данных не был корректно определен, 1С инициализирует параметр значением по умолчанию. Поскольку тип Дата часто идет первым в составных типах или устанавливается по умолчанию при ошибках приведения, система записывает туда пустую дату. Это явный индикатор того, что структура ПараметрыДанных.Элементы разрушена при десериализации.
В ручном режиме код может обращаться к ХранилищеОбщихНастроек и успешно получать данные текущего пользователя. В регламентном задании, если явно не указать пользователя, система попытается прочитать настройки для дефолтного пользователя регламентного задания, и они окажутся пустыми.
Решение: Как правильно заметили в обсуждениях, для внешних или дополнительных обработок надежнее использовать специализированные хранилища или реквизиты справочника ДополнительныеОтчетыИОбработки. Храните настройки (например, XML-строку) в реквизите справочника и явно передавайте их в обработку при запуске.
Рассмотрим безопасный метод работы с настройками. Метод УстановитьЗначениеПараметра работает только тогда, когда параметр уже существует в коллекции. Прямая десериализация непосредственно в рабочий компоновщик может затереть структуру.
Чтобы избежать ошибок, загружайте десериализованные данные в промежуточный объект типа НастройкиКомпоновкиДанных, а затем применяйте их к компоновщику через специальный метод ЗагрузитьНастройки. Это заставит платформу корректно сопоставить загружаемые значения с существующей схемой.
// 1. Инициализируем компоновщик схемой
КомпоновщикТоваров.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(СхемаКомпоновкиДанных));
// 2. Десериализуем настройки из XML во временную переменную
ЗагруженныеНастройки = _ДесериализоватьНастройкиXML(ТекстНастроек);
// 3. Безопасно загружаем настройки
КомпоновщикТоваров.ЗагрузитьНастройки(ЗагруженныеНастройки);
// 4. Теперь можно безопасно устанавливать параметры
КомпоновщикТоваров.Настройки.ПараметрыДанных.УстановитьЗначениеПараметра("ВыгружатьТолькоИзменения", ВыгружатьТолькоИзменения);
Подведем итоги. Ошибка поиска параметра в фоне возникает из-за того, что Компоновщик Настроек теряет свою структуру. Чтобы этого избежать, всегда инициализируйте СКД программно, проверяйте права служебного пользователя на объекты в настройках и используйте метод ЗагрузитьНастройки для безопасного применения десериализованных данных.