Как получить имя пользователя ОС (Windows) при запуске клиента 1С в терминальном режиме?

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

В практике разработки на платформе 1С:Предприятие часто возникают задачи, связанные с интеграцией системы и окружения пользователя. Одной из таких задач является идентификация конкретного сотрудника не по его учетной записи в базе 1С, а по его доменному имени или локальному пользователю операционной системы Windows. Особенно актуален этот вопрос при использовании терминальных серверов (RDP), где несколько пользователей работают на одном физическом или виртуальном сервере, но под разными сеансами ОС.

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

Постановка задачи и ограничения

Представим ситуацию: у нас есть клиент-серверная база 1С. Пользователи подключаются к ней через терминальный сервер (Remote Desktop). Нам необходимо в момент старта системы выяснить:

  1. Имя компьютера, с которого запущен клиент (хотя для терминала это будет имя самого сервера, если не использовать проброс переменных).
  2. Имя пользователя операционной системы (логин Windows), под которым запущен сеанс.

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

Также важно понимать различие контекстов:

Решение 1: Использование COM-объекта WScript.Network

Самым надежным и распространенным способом получения сведений о сетевом окружении в среде Windows является использование системного объекта WScript.Network. Этот объект предоставляет доступ к данным о сети, имени компьютера и имени текущего пользователя.

Поскольку работа с COM-объектами доступна на клиенте (в тонком или толстом клиенте под Windows), мы можем использовать следующий код. Разберем его подробно.

Для начала создадим экземпляр COM-объекта:


// Этот код должен выполняться НА КЛИЕНТЕ (Тонкий клиент, Толстый клиент)
Попытка
    СетеваяОболочка = Новый COMОбъект("WScript.Network");
    ИмяПользователяОС = СетеваяОболочка.UserName;
    ДоменПользователя = СетеваяОболочка.UserDomain;
    ИмяКомпьютера     = СетеваяОболочка.ComputerName;
    
    Сообщить("Пользователь ОС: " + ИмяПользователяОС);
    Сообщить("Домен: " + ДоменПользователя);
Исключение
    // Обработка ситуации, если создание COM-объекта запрещено политиками безопасности
    // или если клиент запущен не под Windows (например, Linux или MacOS)
    ОписаниеОшибки = ОписаниеОшибки();
    ЗаписьЖурналаРегистрации("ПолучениеИмениПользователяОС", 
        УровеньЖурналаРегистрации.Ошибка, , , 
        "Не удалось создать WScript.Network: " + ОписаниеОшибки);
КонецПопытки;

Важные замечания по этому методу:

  1. Метод работает только в операционных системах семейства Windows. Если у вас используются клиенты на Linux, данный код вызовет ошибку, поэтому использование блока Попытка...Исключение обязательно.
  2. В веб-клиенте (запуск через браузер) создание COM-объектов запрещено политиками безопасности браузеров. Этот метод там работать не будет.

Решение 2: Анализ каталога временных файлов (Альтернативный подход)

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

В Windows путь к временной папке пользователя обычно выглядит так: C:\Users\ИмяПользователя\AppData\Local\Temp\. Идея заключается в том, чтобы получить этот путь средствами 1С и "вырезать" из него имя пользователя.


// Пример логики (не рекомендуется для продакшена без проверок)
ПолныйПуть = КаталогВременныхФайлов(); // Например: "C:\Users\Serg_1960\AppData\Local\Temp\"
МассивЧастей = СтрРазделить(ПолныйПуть, "\");

// В стандартной структуре Windows имя пользователя часто находится на определенной позиции
// Но это ненадежно, так как структура может меняться.

Почему этот метод ненадежен:

Поэтому мы рекомендуем использовать первый метод с WScript.Network как основной.

Архитектурная реализация: Передача данных с Клиента на Сервер

Самая сложная часть задачи — это не просто получить имя, а сделать его доступным в глобальном контексте приложения, чтобы использовать в отчетах, документах или правах доступа. Так как код WScript.Network работает только на клиенте, а основные алгоритмы выполняются на сервере, нам нужно передать это значение.

Рассмотрим правильный паттерн реализации через Параметры Сеанса.

Шаг 1. Создание Параметра сеанса

В дереве конфигурации создадим новый Параметр сеанса, назовем его ТекущийПользовательОС. Тип значения — Строка (длина 50-100 символов).

Шаг 2. Общий модуль для установки параметра

Создадим Общий модуль (или используем существующий), у которого установлены флаги "Сервер" и "Вызов сервера". Назовем его, например, УправлениеСеансомСервер.


// Общий модуль: УправлениеСеансомСервер
// Флажки: Сервер, Вызов сервера

Процедура УстановитьИмяПользователяОС(Знач ИмяПользователя) Экспорт
    // Проверка прав доступа к параметрам сеанса может потребоваться, если используется RLS
    ПараметрыСеанса.ТекущийПользовательОС = ИмяПользователя;
КонецПроцедуры

Шаг 3. Клиентский код при начале работы системы

В модуле управляемого приложения (файл ManagedApplicationModule) используем событие ПриНачалеРаботыСистемы или ПередНачаломРаботыСистемы. Именно здесь мы получаем данные и сразу отправляем их на сервер.


// Модуль управляемого приложения

Процедура ПриНачалеРаботыСистемы()
    
    // Получаем имя пользователя Windows
    ИмяUserOS = "";
    
    #Если ВебКлиент Тогда
        // Для веб-клиента логика должна быть другой (например, через расширение браузера)
        // В данном примере пропускаем
    #ИначеЕсли МобильныйКлиент Тогда
        // Для мобильного клиента WScript недоступен
    #Иначе
        // Тонкий клиент / Толстый клиент (Windows)
        Попытка
            СетеваяОболочка = Новый COMОбъект("WScript.Network");
            ИмяUserOS = СетеваяОболочка.UserName;
        Исключение
            // Логирование ошибки
        КонецПопытки;
    #КонецЕсли
    
    // Если удалось определить имя, отправляем его на сервер
    Если ЗначениеЗаполнено(ИмяUserOS) Тогда
        УправлениеСеансомСервер.УстановитьИмяПользователяОС(ИмяUserOS);
    КонецЕсли;

КонецПроцедуры

Особенности работы в Терминальном режиме (RDP)

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

При использовании WScript.Network:

Если вам дополнительно потребуется узнать имя клиентской станции, с которой пришло RDP-подключение (например, чтобы знать, что бухгалтер зашел из дома, а не из офиса), использование WScript.Network.ComputerName введет вас в заблуждение — у всех пользователей оно будет одинаковым (имя сервера).

Чтобы узнать настоящее имя клиентского ПК (откуда идет подключение), необходимо читать переменную среды CLIENTNAME. Это также делается через COM-объект, но другой — WScript.Shell.


// Получение имени клиентской станции в RDP-сессии
Попытка
    WshShell = Новый COMОбъект("WScript.Shell");
    // Читаем переменную окружения
    ПроцессОкружения = WshShell.Environment("Process");
    ИмяКлиентаRDP = ПроцессОкружения.Item("CLIENTNAME");
    
    Если ЗначениеЗаполнено(ИмяКлиентаRDP) Тогда
        Сообщить("Подключение с компьютера: " + ИмяКлиентаRDP);
    Иначе
        Сообщить("Это локальная сессия (не RDP) или переменная недоступна.");
    КонецЕсли;
Исключение
    Сообщить("Не удалось получить переменные окружения.");
КонецПопытки;

Выводы и рекомендации

  1. Для получения имени пользователя ОС Windows используйте COM-объект WScript.Network и его свойство UserName. Это наиболее стабильный метод.
  2. Код получения данных должен выполняться строго на клиенте.
  3. Для использования полученных данных в дальнейшей логике программы (в серверных процедурах проведения, отчетах) передавайте значение в Параметры сеанса при старте системы.
  4. Учитывайте, что метод работает только в среде Windows. Для кроссплатформенных конфигураций обязательно используйте конструкции Попытка...Исключение.
  5. Избегайте парсинга путей к системным папкам (Temp, AppData) — это ненадежно и зависит от настроек конкретной ОС.
← На главную