Как правильно передать параметр objectGUID в ADO-запросе к LDAP из 1С

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

При работе с Active Directory (AD) через механизмы ADO и COM-объекты в 1С часто возникает необходимость найти конкретную запись по её уникальному идентификатору objectGUID. Однако при попытке передать GUID через параметры Command.Parameters или обычным сопоставлением со строкой в секции WHERE разработчики сталкиваются с ошибками провайдера ADsDSOObject.

В этой статье мы разберем причину возникновения проблемы, проанализируем порядок байтов при конвертации GUID и рассмотрим практические способы поиска и получения объектов по objectGUID из 1С.

Почему возникает ошибка при передаче objectGUID

Выясним особенности работы OLE DB провайдера для Active Directory (ADsDSOObject):

  1. Отсутствие поддержки параметров в ADsDSOObject: Провайдер ADO для LDAP не поддерживает подстановку бинарных параметров через знак ? и коллекцию Command.Parameters. При попытке передать параметр подсистема возвращает исключение Provider: Произошла одна или несколько ошибок во время обработки команды.
  2. Ограничения SQL-диалекта LDAP: В запросах к LDAP через ADO недоступны привычные функции преобразования типов CAST и CONVERT.
  3. Особенности хранения objectGUID: В Active Directory атрибут objectGUID хранится в виде 16-байтового массива (тип OctetString). Чтобы выполнить выборку по строковому GUID (например, {E2B589DD-DE54-475E-BCD4-DD894F6BF9EE}), его необходимо перевести в бинарный вид с учетом правил хранения данных Microsoft GUID (Little-Endian для первых трех групп).

Способ 1. Формирование бинарной строки в секции WHERE (SQL-синтаксис ADO)

Рассмотрим, как правильно подготовить строковый GUID для подстановки непосредственно в текст SQL-запроса. Для этого требуется переставить байты в соответствии с правилами структуры GUID и записать их через обратный слэш \ в одиночных кавычках.

Правило перестановки байтов из строкового GUID (на примере E2B589DD-DE54-475E-BCD4-DD894F6BF9EE):

  1. Первые 4 байта (E2B589DD) записываются в обратном порядке: DD, 89, B5, E2.
  2. Следующие 2 байта (DE54) записываются в обратном порядке: 54, DE.
  3. Следующие 2 байта (475E) записываются в обратном порядке: 5E, 47.
  4. Оставшиеся 8 байт (BCD4-DD894F6BF9EE) записываются в прямом порядке: BC, D4, DD, 89, 4F, 6B, F9, EE.

Посмотрим на пример функции 1С, которая преобразует стандартную строку GUID в формат для SQL-запроса ADO:


Функция ПодготовитьGUIDДляLDAP(Знач СтрокаGUID) Экспорт
    // Удаляем скобки и дефисы
    Стр = СтрЗаменить(СтрокаGUID, "{", "");
    Стр = СтрЗаменить(Стр, "}", "");
    Стр = СтрЗаменить(Стр, "-", "");
    
    Если СтрДлина(Стр) <> 32 Тогда
        Возврат "";
    КонецЕсли;
    
    // Перестановка байтов (Little-Endian для первых трех секций)
    Результат = "\" + Сред(Стр, 7, 2) + "\" + Сред(Стр, 5, 2) + "\" + Сред(Стр, 3, 2) + "\" + Сред(Стр, 1, 2)
              + "\" + Сред(Стр, 11, 2) + "\" + Сред(Стр, 9, 2)
              + "\" + Сред(Стр, 15, 2) + "\" + Сред(Стр, 13, 2)
              + "\" + Сред(Стр, 17, 2) + "\" + Сред(Стр, 19, 2)
              + "\" + Сред(Стр, 21, 2) + "\" + Сред(Стр, 23, 2)
              + "\" + Сред(Стр, 25, 2) + "\" + Сред(Стр, 27, 2)
              + "\" + Сред(Стр, 29, 2) + "\" + Сред(Стр, 31, 2);
              
    Возврат Результат;
КонецФункции

Разберем пример исполнения запроса ADO с созданной строкой:


ГуидСтр = "{E2B589DD-DE54-475E-BCD4-DD894F6BF9EE}";
LdapGuid = ПодготовитьGUIDДляLDAP(ГуидСтр);

ADODB_Command = Новый COMОбъект("ADODB.Command");
ADODB_Command.ActiveConnection = Connection;
ADODB_Command.Properties("Page Size").Value = 1000;
ADODB_Command.Properties("Timeout").Value = 30;
ADODB_Command.Properties("Cache Results").Value = Ложь;

// Формируем текст запроса с экранированной байтовой строкой
ТекстЗапроса = "SELECT ADsPath, objectGUID, sAMAccountName, userPrincipalName " +
               "FROM 'LDAP://" + Адрес + "/" + RootPath + "' " +
               "WHERE objectGUID = '" + LdapGuid + "'";

ADODB_Command.CommandText = ТекстЗапроса;
rs = ADODB_Command.Execute();

Способ 2. Прямое обращение к объекту по GUID (Direct Binding)

Если задача состоит в том, чтобы просто получить данные конкретного объекта Active Directory по известному GUID, можно обойтись без выполнения поиска через ADODB.Command. В AD поддерживается прямое связывание с объектом по пути вида LDAP://<GUID=...>.

Проанализируем применение прямого связывания в коде 1С:


ГуидСтр = "E2B589DD-DE54-475E-BCD4-DD894F6BF9EE";
ГуидСтр = СтрЗаменить(СтрЗаменить(ГуидСтр, "{", ""), "}", "");

ПутьLDAP = "LDAP://<GUID=" + ГуидСтр + ">";

Попытка
    ОбъектAD = ПолучитьCOMОбъект(ПутьLDAP);
    ЛогинПользователя = ОбъектAD.Get("sAMAccountName");
    UPN = ОбъектAD.Get("userPrincipalName");
Исключение
    Сообщить("Не удалось найти объект в AD по GUID: " + ОписаниеОшибки());
КонецПопытки;

Преимущество данного подхода: при прямом связывании не требуется менять порядок байтов или применять слэши — платформа Active Directory сама преобразует стандартный строковый GUID.

Способ 3. Чтение objectGUID из результатов ADO в переменную 1С

При получении поля objectGUID из результата запроса ADO (rs.Fields("objectGUID").Value) возвращается массив байтов в формате COMSafeArray. Для дальнейшего сохранения GUID в текстовый реквизит информационной базы 1С необходимо выполнить обратную конвертацию.

Рассмотрим пример функции перевода байтового массива в строку формата GUID:


Функция ПреобразоватьCOMGUIDВСтроку(COMobjectGUID) Экспорт
    
    МассивБайт = COMobjectGUID.Выгрузить(); // Выгружаем COMSafeArray в Массив 1С
    
    // Вспомогательная логика перевода байта в 2-символьный HEX-вид
    GUID = "{";
    GUID = GUID + НЕХ(МассивБайт[3]) + НЕХ(МассивБайт[2]) + НЕХ(МассивБайт[1]) + НЕХ(МассивБайт[0]) + "-";
    GUID = GUID + НЕХ(МассивБайт[5]) + НЕХ(МассивБайт[4]) + "-";
    GUID = GUID + НЕХ(МассивБайт[7]) + НЕХ(МассивБайт[6]) + "-";
    GUID = GUID + НЕХ(МассивБайт[8]) + НЕХ(МассивБайт[9]) + "-";
    GUID = GUID + НЕХ(МассивБайт[10]) + НЕХ(МассивБайт[11]) + НЕХ(МассивБайт[12]) + НЕХ(МассивБайт[13]) + НЕХ(МассивБайт[14]) + НЕХ(МассивБайт[15]);
    GUID = GUID + "}";
    
    Возврат GUID;
КонецФункции

Таким образом, мы разжились инструментами для полноценной работы с objectGUID. Для построения выборок с фильтрами в ADO используйте подготовку байтовой строки через слэши, а для точечной работы с известным объектом применяйте прямое связывание по пути LDAP://<GUID=...>.

← На главную