Почему список пользователей домена в 1С ограничен 100 записями и как это исправить

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

При настройке авторизации пользователей через операционную систему многие разработчики сталкиваются с досадной проблемой: стандартная функция платформы ПользователиОС() (или устаревшая ПользователиWindows()) возвращает таблицу значений, содержащую ровно 100 пользователей, хотя в домене Active Directory их могут быть тысячи. Это создает серьезные неудобства, так как администраторам приходится вводить имена учетных записей вручную вместо выбора из списка.

В этой статье мы подробно проанализируем ситуацию, выясним технические причины такого поведения системы и рассмотрим несколько способов решения проблемы — от системных обновлений до написания альтернативных функций на языке 1С.

Выясним причину: почему именно 100?

Разберем ситуацию с технической стороны. Ограничение в 100 записей не является случайным числом или настройкой 1С. Это стандартный размер порции данных (буфера), который возвращает низкоуровневая функция WinAPI SamrQueryDisplayInformation при использовании протокола SAMR (Security Account Manager Remote Protocol).

Когда платформа 1С запрашивает список пользователей у контроллера домена, происходит следующее:

  1. Клиент (1С) отправляет запрос к серверу на перечисление объектов.
  2. Сервер возвращает первую "страницу" данных, которая по умолчанию составляет 100 записей.
  3. В нормальных условиях клиент должен запросить следующую страницу, однако из-за специфических ошибок в реализации сетевого стека Windows (особенно в Windows Server 2019) происходит сбой согласования буфера (STATUS_BUFFER_OVERFLOW).
  4. В итоге 1С получает только первую порцию данных и считает, что список завершен.

Важно понимать, что это не ограничение MaxPageSize в LDAP (где лимит обычно составляет 1000 записей), а именно специфика работы протокола SAMR, который 1С использует "под капотом" в своих стандартных функциях.

Способ 1. Обновление платформы и операционной системы

Первым делом проанализируем программное окружение. Опыт показывает, что проблема наиболее остро проявляется на связке Windows Server 2019 и старых релизов платформы 1С (ниже 8.3.15).

Рекомендуемые действия:

  1. Обновите платформу 1С до актуальных релизов (минимум 8.3.18.1289 и выше). В новых версиях механизмы взаимодействия с системными вызовами были оптимизированы.
  2. Установите накопительные обновления на контроллеры домена. Для Windows Server 2019 критически важным является обновление KB4516077 (сентябрь 2019 года) или более свежие кумулятивные патчи, которые исправляют регрессию в обработке RPC-запросов.
  3. Проверьте режим совместимости конфигурации. В некоторых случаях режим совместимости с версиями 8.3.8 или ниже заставляет платформу использовать устаревшие интерфейсы опроса ОС.

Способ 2. Получение списка через COM-объект WinNT

Если обновление системы невозможно или не дает результата, мы можем написать собственную функцию для получения списка пользователей. Рассмотрим пример использования провайдера WinNT. Этот метод позволяет опрашивать группы домена напрямую.

Проанализируем пример кода:


Функция ПолучитьСписокПользователейВГруппеДомена(ИмяДомена, ИмяГруппы) Экспорт
    Результат = Новый Массив;
    Попытка
        // Подключаемся к конкретной группе домена через WinNT
        objNameSpace = ПолучитьCOMОбъект("WinNT://" + СокрЛП(ИмяДомена) + "/" + СокрЛП(ИмяГруппы) + ", Group");
        
        Для каждого item Из objNameSpace.Members Цикл
            // Добавляем имя пользователя в массив
            Результат.Добавить(item.Name);
        КонецЦикла;
    Исключение
        // Обработка ошибок доступа или отсутствия группы
        ЗаписатьЛогСобытий("Ошибка получения пользователей: " + ОписаниеОшибки());
    КонецПопытки;
    
    Возврат Результат;
КонецФункции

Преимущество: метод работает стабильно и обходит ограничение в 100 записей. Недостаток: метод WinNT работает медленнее, чем LDAP, и требует наличия прав на чтение состава групп.

Способ 3. Использование ADO и LDAP (рекомендуемый метод)

Самый надежный и профессиональный способ получения данных из Active Directory — это использование технологии ADSI через COM-объект ADODB.Connection. Этот метод позволяет выполнять SQL-подобные запросы к базе данных домена и полностью контролировать процесс получения данных.

Разберем реализацию по шагам:


&НаСервере
Процедура ОбновитьСписокПользователейAD()
    // Инициализируем системные объекты
    АДСИ = Новый COMОбъект("ADSystemInfo");
    Домен = АДСИ.DomainDNSName;
    
    Соединение = Новый COMОбъект("ADODB.Connection");
    Соединение.Provider = "ADSDSOObject";
    Соединение.Open("Active Directory Provider");
    
    // Формируем текст запроса. 
    // sAMAccountName - логин, displayName - полное имя
    // subTree означает поиск по всему дереву каталога
    ТекстЗапроса = "<LDAP://" + Домен + ">;(&(objectCategory=person)(objectClass=user));sAMAccountName,displayName,adspath;subTree";
    
    Команда = Новый COMОбъект("ADODB.Command");
    Команда.ActiveConnection = Соединение;
    Команда.CommandText = ТекстЗапроса;
    
    // Настройка постраничного вывода (важно для больших списков!)
    Команда.Properties("Page Size").Value = 1000;
    Команда.Properties("Timeout").Value = 30;
    
    Выборка = Команда.Execute();
    
    Пока НЕ Выборка.EOF Цикл
        Логин = Выборка.Fields("sAMAccountName").Value;
        ПолноеИмя = Выборка.Fields("displayName").Value;
        
        // Здесь можно записывать данные в справочник или таблицу значений
        // Например: НоваяСтрока = ТЗПользователи.Добавить();
        
        Выборка.MoveNext();
    КонецЦикла;
    
    Соединение.Close();
КонецПроцедуры

В этом примере мы явно указываем Page Size = 1000. Это заставляет драйвер LDAP запрашивать данные порциями, что гарантирует получение всех записей из домена, даже если их десятки тысяч.

Способ 4. Получение данных через WMI

Еще один альтернативный вариант — использование инструментария WMI (Windows Management Instrumentation). Рассмотрим, как можно получить список учетных записей через объект Win32_UserAccount.

Посмотрим на пример кода:


Функция ПолучитьПользователейЧерезWMI()
    Список = Новый Массив;
    Попытка
        Локатор = Новый COMОбъект("WbemScripting.SWbemLocator");
        Сервис = Локатор.ConnectServer(".", "root\cimv2");
        
        // Запрос к системному классу аккаунтов
        Запрос = Сервис.ExecQuery("SELECT Name, Domain FROM Win32_UserAccount WHERE Disabled = False");
        
        Для каждого Объект Из Запрос Цикл
            Список.Добавить(Объект.Domain + "\" + Объект.Name);
        КонецЦикла;
    Исключение
        Сообщить("Ошибка WMI: " + ОписаниеОшибки());
    КонецПопытки;
    
    Возврат Список;
КонецФункции

Важный нюанс: при использовании WMI в клиент-серверном варианте запрос будет выполняться от имени учетной записи, под которой запущена служба "1C:Enterprise 8.3 Server Agent". Убедитесь, что у этой учетной записи достаточно прав для чтения данных из Active Directory.

Подведем итоги

Проанализировав ситуацию, можно сделать вывод, что лимит в 100 пользователей — это не приговор, а следствие технических особенностей взаимодействия 1С с устаревшими протоколами Windows в определенных версиях ОС.

Краткий чек-лист для исправления:

  1. Проверьте версию платформы (рекомендуется 8.3.18+).
  2. Убедитесь, что на контроллере домена установлены все актуальные обновления безопасности.
  3. Если стандартные методы ПользователиОС() продолжают выдавать 100 строк, используйте ADO/LDAP запросы. Это наиболее гибкий и быстрый способ, позволяющий фильтровать пользователей (например, исключать заблокированные учетные записи или технические аккаунты).
  4. При использовании клиент-серверной архитектуры помните: запросы к домену выполняет сервер 1С. Запуск службы сервера от имени доменного пользователя с правами Read all user information часто решает проблемы с неполным списком.

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

← На главную