При интеграции 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).
Рассмотрим стратегию, которая позволит нам обойти это ограничение. Мы разделим задачу на два этапа:
ADsPath.ADsPath, мы подключаемся к конкретному объекту напрямую через протокол LDAP и выполняем запись данных.Сначала нам нужно найти пользователя в домене. Обратите внимание, что в тексте запроса обязательно должен присутствовать атрибут 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='" + ДоменноеИмя + "'";
Теперь разберем, как изменить данные. Вместо того чтобы писать ВыборкаАДО.Fields("telephoneNumber").Value = "12345", что и вызывает ошибку, мы обратимся к самому объекту Active Directory. Выясним, как это сделать правильно, используя методы Put и SetInfo.
ВыборкаАДО = КомандаАДО.Execute();
Пока НЕ ВыборкаАДО.EOF Цикл
// Получаем уникальный путь к объекту в AD
ПутьКОбъекту = ВыборкаАДО.Fields("ADsPath").Value;
Попытка
// Подключаемся напрямую к объекту пользователя через ADSI
ПользовательОбъект = ПолучитьCOMОбъект(ПутьКОбъекту);
// Устанавливаем новое значение атрибута
НовыйНомер = "12345";
ПользовательОбъект.Put("telephoneNumber", НовыйНомер);
// КРИТИЧЕСКИ ВАЖНО: сохраняем изменения в базе AD
ПользовательОбъект.SetInfo();
Сообщить("Данные для пользователя " + ДоменноеИмя + " успешно обновлены.");
Исключение
Сообщить("Ошибка при записи в AD: " + ОписаниеОшибки());
КонецПопытки;
ВыборкаАДО.MoveNext();
КонецЦикла;
Проанализируем работу метода SetInfo(). Когда вы вызываете Put(), изменения вносятся только в локальный кэш свойств объекта в оперативной памяти вашего компьютера. Если вы завершите работу программы, не вызвав SetInfo(), все внесенные изменения будут потеряны, и в Active Directory ничего не изменится. Метод SetInfo() отправляет накопленные изменения из кэша на контроллер домена.
Иногда требуется работать с атрибутами, которые могут содержать массив значений (например, otherTelephone или список групп). В таких случаях метод Put может работать некорректно. Рассмотрим использование метода PutEx. Он принимает три параметра: тип операции, имя атрибута и массив значений.
Типы операций PutEx:
Пример очистки поля номера телефона:
// Очистка поля (константа 1)
ПользовательОбъект.PutEx(1, "telephoneNumber", "");
ПользовательОбъект.SetInfo();
Если код отрабатывает без ошибок, но данные в AD не меняются, или возникает ошибка «Доступ запрещен», необходимо проверить контекст исполнения. Выясним основные причины проблем с правами:
LocalSystem или специальной локальной записью, у которой нет прав в домене. В этом случае необходимо либо сменить учетную запись службы сервера на доменную, либо явно указывать логин/пароль администратора при создании COM-объекта.SWbemLocator или специфические параметры открытия LDAP через ADS_SECURE_AUTHENTICATION, но в большинстве случаев достаточно запуска сеанса 1С от имени пользователя с нужными правами.Мы выяснили, что ошибка «Recordset не поддерживает обновление» — это не баг, а архитектурная особенность провайдера ADSDSOObject. Для успешного редактирования данных в Active Directory всегда используйте комбинированный подход: поиск через ADO для получения ADsPath и последующее редактирование через LDAP объект с обязательным вызовом SetInfo(). Это гарантирует надежную работу вашей интеграции и корректное сохранение данных в контроллере домена.