Как обновить данные в Active Directory из 1С, если возникает ошибка Recordset не поддерживает обновление

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

При интеграции 1С с Active Directory (AD) разработчики часто используют технологию ADO (Active Data Objects) для поиска пользователей или групп. Однако при попытке не только прочитать, но и изменить данные (например, записать номер телефона или почту), возникает ошибка: «Произошла исключительная ситуация (ADODB.Field): Текущий объект Recordset не поддерживает обновление. Это связано с ограничением поставщика или с выбранным типом блокировки». В этой статье мы подробно разберем, почему это происходит и как правильно организовать запись данных в AD из среды 1С.

Разбор причины ошибки

Проанализируем ситуацию: для доступа к данным Active Directory в коде используется провайдер ADSDSOObject. Это специализированный OLE DB провайдер для работы со службами каталогов. Его главная особенность заключается в том, что он предназначен только для чтения. Когда мы выполняем запрос SELECT через этот провайдер, возвращаемый объект Recordset всегда имеет тип курсора "только чтение" (read-only).

Попытки изменить свойство LockType или CursorType у объекта Recordset не принесут результата, так как ограничение заложено на уровне самого поставщика данных ADSDSOObject. Он не поддерживает SQL-команду UPDATE и не позволяет редактировать поля напрямую в выборке. Чтобы внести изменения в объект домена, нам необходимо использовать другой программный интерфейс — ADSI (Active Directory Service Interfaces).

Правильный алгоритм изменения данных

Рассмотрим стратегию, которая позволит нам обойти это ограничение. Мы разделим задачу на два этапа:

  1. Поиск объекта: Используем привычный ADO-запрос для поиска нужного пользователя и получения его уникального пути в каталоге — атрибута ADsPath.
  2. Модификация объекта: Используя полученный ADsPath, мы подключаемся к конкретному объекту напрямую через протокол LDAP и выполняем запись данных.

Шаг 1: Подготовка поискового запроса

Сначала нам нужно найти пользователя в домене. Обратите внимание, что в тексте запроса обязательно должен присутствовать атрибут ADsPath. Именно он является «ключом», который позволит нам обратиться к объекту для редактирования. Проанализируем пример формирования запроса:


КомандаАДО = Новый COMОбъект("ADODB.Command");
СоединениеАДО = Новый COMОбъект("ADODB.Connection");
СоединениеАДО.Provider = "ADSDSOObject";
СоединениеАДО.Open("Active Directory Provider");

КомандаАДО.ActiveConnection = СоединениеАДО;
ДоменноеИмя = "UserTest"; // Логин пользователя

// Важно: выбираем ADsPath
КомандаАДО.CommandText = "SELECT ADsPath, sAMAccountName, telephoneNumber 
                         |FROM 'LDAP://dc=syn,dc=local' 
                         |WHERE objectClass='user' AND sAMAccountName='" + ДоменноеИмя + "'";

Шаг 2: Обработка результатов и запись данных

Теперь разберем, как изменить данные. Вместо того чтобы писать ВыборкаАДО.Fields("telephoneNumber").Value = "12345", что и вызывает ошибку, мы обратимся к самому объекту Active Directory. Выясним, как это сделать правильно, используя методы Put и SetInfo.


ВыборкаАДО = КомандаАДО.Execute();

Пока НЕ ВыборкаАДО.EOF Цикл
    // Получаем уникальный путь к объекту в AD
    ПутьКОбъекту = ВыборкаАДО.Fields("ADsPath").Value;
    
    Попытка
        // Подключаемся напрямую к объекту пользователя через ADSI
        ПользовательОбъект = ПолучитьCOMОбъект(ПутьКОбъекту);
        
        // Устанавливаем новое значение атрибута
        НовыйНомер = "12345";
        ПользовательОбъект.Put("telephoneNumber", НовыйНомер);
        
        // КРИТИЧЕСКИ ВАЖНО: сохраняем изменения в базе AD
        ПользовательОбъект.SetInfo();
        
        Сообщить("Данные для пользователя " + ДоменноеИмя + " успешно обновлены.");
    Исключение
        Сообщить("Ошибка при записи в AD: " + ОписаниеОшибки());
    КонецПопытки;
    
    ВыборкаАДО.MoveNext();
КонецЦикла;

Важные нюансы метода SetInfo()

Проанализируем работу метода SetInfo(). Когда вы вызываете Put(), изменения вносятся только в локальный кэш свойств объекта в оперативной памяти вашего компьютера. Если вы завершите работу программы, не вызвав SetInfo(), все внесенные изменения будут потеряны, и в Active Directory ничего не изменится. Метод SetInfo() отправляет накопленные изменения из кэша на контроллер домена.

Работа с многозначными атрибутами (PutEx)

Иногда требуется работать с атрибутами, которые могут содержать массив значений (например, otherTelephone или список групп). В таких случаях метод Put может работать некорректно. Рассмотрим использование метода PutEx. Он принимает три параметра: тип операции, имя атрибута и массив значений.

Типы операций PutEx:

Пример очистки поля номера телефона:


// Очистка поля (константа 1)
ПользовательОбъект.PutEx(1, "telephoneNumber", "");
ПользовательОбъект.SetInfo();

Права доступа и безопасность

Если код отрабатывает без ошибок, но данные в AD не меняются, или возникает ошибка «Доступ запрещен», необходимо проверить контекст исполнения. Выясним основные причины проблем с правами:

  1. Пользователь 1С: Если 1С запущена в файловом режиме, запись в AD идет от имени текущего пользователя Windows. У этого пользователя должны быть делегированы права на правку конкретных атрибутов в соответствующем подразделении (OU) домена.
  2. Серверный режим: В клиент-серверном варианте код часто выполняется на стороне сервера 1С. По умолчанию служба сервера 1С работает под учетной записью LocalSystem или специальной локальной записью, у которой нет прав в домене. В этом случае необходимо либо сменить учетную запись службы сервера на доменную, либо явно указывать логин/пароль администратора при создании COM-объекта.
  3. Явное указание учетных данных: Для безопасного подключения с правами администратора можно использовать объект SWbemLocator или специфические параметры открытия LDAP через ADS_SECURE_AUTHENTICATION, но в большинстве случаев достаточно запуска сеанса 1С от имени пользователя с нужными правами.

Заключение

Мы выяснили, что ошибка «Recordset не поддерживает обновление» — это не баг, а архитектурная особенность провайдера ADSDSOObject. Для успешного редактирования данных в Active Directory всегда используйте комбинированный подход: поиск через ADO для получения ADsPath и последующее редактирование через LDAP объект с обязательным вызовом SetInfo(). Это гарантирует надежную работу вашей интеграции и корректное сохранение данных в контроллере домена.

← На главную