Почему ХранилищеОбщихНастроек.Загрузить() возвращает "Неопределено" при указании пользователя?

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

В практике программирования на платформе 1С:Предприятие мы часто сталкиваемся с необходимостью программного сохранения и чтения пользовательских настроек. Рассмотрим весьма распространенную ситуацию, когда разработчик пытается получить настройки конкретного пользователя, но система упорно возвращает Неопределено. Проанализируем, почему возникает такая ошибка и как правильно работать с объектом ХранилищеОбщихНастроек.

Разберем суть проблемы

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


Настройка = ХранилищеОбщихНастроек.Загрузить(
    "КлючОбъекта", 
    "КлючНастроек", 
    , 
    ПользователиКлиентСервер.ТекущийПользователь()
);

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

Посмотрим на типы передаваемых параметров

Главная ошибка кроется в четвертом параметре метода Загрузить(). Разберем по шагам, что именно мы туда передаем. Функция ПользователиКлиентСервер.ТекущийПользователь() возвращает ссылку на элемент справочника "Пользователи".

Однако, согласно синтакс-помощнику платформы, методы ХранилищеОбщихНастроек.Загрузить() и Сохранить() ожидают в этом параметре строго тип Строка. Эта строка должна содержать имя пользователя Информационной Базы (логин), как оно задано в Конфигураторе, а не уникальный идентификатор (УИД) и не ссылку на справочник.

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

Проанализируем ситуацию с переименованием пользователей

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

  1. Пользовательские настройки в 1С жестко привязаны к строковому имени (логину).
  2. УИДы пользователей в хранилище настроек не фигурируют.
  3. Если пользователя переименовали, его старые настройки остаются в хранилище привязанными к старому имени. Они становятся "сиротами".
  4. Система при попытке чтения по новому имени закономерно ничего не находит.

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

Проверим права доступа и контекст выполнения

Рассмотрим дополнительные факторы, которые могут влиять на результат метода Загрузить():

  1. Собственные настройки: У пользователя обязательно должна быть роль с правом СохранениеДанныхПользователя. Без этого права механизмы хранилища настроек не будут работать корректно.
  2. Чужие настройки: Чтение и запись настроек другого пользователя требует полных административных прав (или наличия права АдминистрированиеДанных). Если код выполняется под обычным пользователем, попытка прочитать чужие настройки потерпит неудачу. Для обхода этого ограничения необходимо использовать привилегированный режим:
    
    УстановитьПривилегированныйРежим(Истина);
    Настройка = ХранилищеОбщихНастроек.Загрузить("КлючОбъекта", "КлючНастроек", , "ИмяПользователяИБ");
    УстановитьПривилегированныйРежим(Ложь);
    
  3. Фоновые и регламентные задания: Если наш код крутится в регламентном задании, следует помнить, что оно выполняется на сервере без контекста сеанса конкретного пользователя. Если явно не передать правильное строковое имя пользователя, платформа будет искать настройки для системного пользователя (по умолчанию), которых не существует.

Рекомендации по использованию БСП

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


// Вместо прямого обращения используем методы ОбщегоНазначения
Настройка = ОбщегоНазначения.ХранилищеОбщихНастроекЗагрузить(
    "КлючОбъекта", 
    "КлючНастроек"
);

Почему это лучше? Проанализируем преимущества:

Хак с несуществующим пользователем

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


УстановитьПривилегированныйРежим(Истина);
ХранилищеОбщихНастроек.Сохранить(
    "МояПодсистема_ГлобальныеНастройки", 
    "ПараметрыИнтеграции", 
    СтруктураНастроек, 
    , 
    "#ОбщиеНастройкиСистемы"
);

Поскольку логина "#ОбщиеНастройкиСистемы" в информационной базе нет, никто из реальных пользователей случайно не перезапишет эти данные при входе или выходе. Получать их программно можно также из-под привилегированного режима, жестко передавая эту строку в метод загрузки.

Подведем итог: При работе с ХранилищеОбщихНастроек всегда следите за типами данных. Передавайте только строковый логин пользователя из информационной базы, учитывайте наличие прав (или используйте привилегированный режим) и помните об отсутствии привязки настроек к уникальному идентификатору (УИДу) при переименовании пользователей.

← На главную