Как получить имя терминального клиента (компьютера пользователя) вместо имени сервера 1С

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

В процессе разработки в среде 1С:Предприятие часто возникает задача идентификации конкретного рабочего места пользователя. Стандартная функция ИмяКомпьютера() ведет себя по-разному в зависимости от контекста выполнения. Если код исполняется на стороне сервера (например, в модуле объекта или общем модуле с признаком "Сервер"), эта функция вернет сетевое имя сервера, на котором установлена служба 1С, а не имя ПК пользователя. Особенно остро эта проблема проявляется при работе в терминальном режиме (RDP), где все пользователи фактически работают "внутри" одного сервера.

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

Метод 1: Использование свойств сеанса информационной базы

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

Для реализации этого метода нам потребуется получить номер текущего сеанса и найти его в общем списке активных сеансов. Разберем код по шагам:


// Получаем номер текущего сеанса
ТекНомерСеанса = НомерСеансаИнформационнойБазы();

// Извлекаем массив всех активных сеансов
МассивСеансов = ПолучитьСеансыИнформационнойБазы();

// Ищем наш сеанс в цикле
Для каждого Сеанс Из МассивСеансов Цикл
    Если Сеанс.НомерСеанса = ТекНомерСеанса Тогда
        ИмяТерминала = Сеанс.ИмяКомпьютера;
        Сообщить("Имя компьютера клиента: " + ИмяТерминала);
        Прервать;
    КонецЕсли;
КонецЦикла;

Важное ограничение: Метод ПолучитьСеансыИнформационнойБазы() требует наличия у пользователя административных прав (роль "Администрирование"). Если обычный пользователь попытается выполнить этот код, система выдаст ошибку доступа. Поэтому данный метод лучше всего подходит для регламентных задач или функций, выполняемых под полными правами в привилегированном модуле.

Метод 2: Работа с переменными окружения через WScript.Shell

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

Проанализируем основные переменные, которые нам интересны:

Для чтения этих переменных в 1С мы будем использовать COM-объект Wscript.Shell. Рассмотрим пример кода:


Попытка
    WshShell = Новый COMОбъект("Wscript.Shell");
    // Пытаемся получить имя удаленного клиента
    ИмяКлиента = WshShell.ExpandEnvironmentStrings("%CLIENTNAME%");
    
    // Если переменная пустая (пользователь работает локально, а не по RDP)
    Если ИмяКлиента = "%CLIENTNAME%" Или ПустаяСтрока(ИмяКлиента) Тогда
        ИмяКлиента = WshShell.ExpandEnvironmentStrings("%COMPUTERNAME%");
    КонецЕсли;
    
    Сообщить("Вы подключены с компьютера: " + ИмяКлиента);
Исключение
    Сообщить("Не удалось инициализировать Wscript.Shell: " + ОписаниеОшибки());
КонецПопытки;

Этот метод считается более универсальным для клиентских приложений, так как он не требует специальных прав доступа в 1С. Однако стоит помнить, что в некоторых организациях использование COM-объектов может быть ограничено политиками безопасности (хотя Wscript.Shell блокируют редко).

Метод 3: Использование Библиотеки стандартных подсистем (БСП)

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

Функция ОбщегоНазначения.ИмяКомпьютера() внутри себя часто содержит логику проверки: если вызов происходит на клиенте, возвращается локальное имя. Но если вам нужно гарантированно получить терминальное имя в серверном коде, вам все равно придется передавать его с клиента при запуске системы или использовать параметры сеанса.

Посмотрим на пример записи имени клиента в параметр сеанса при начале работы системы:


// В модуле управляемого приложения
Процедура ПриНачалеРаботыСистемы()
    // Этот код выполняется на стороне клиента
    ИмяЭтогоРобочегоМеста = ИмяКомпьютера(); 
    // Передаем значение на сервер для записи в параметр сеанса
    УстановитьПараметрСеансаТекущееИмяКлиента(ИмяЭтогоРобочегоМеста);
КонецПроцедуры

Продвинутый анализ: Реестр и IP-адреса

В некоторых сложных случаях (например, при каскадном подключении RDP-in-RDP) переменная %CLIENTNAME% может вернуть имя промежуточного сервера. Чтобы получить более точные данные, программисты обращаются к системному реестру. В ветке HKEY_CURRENT_USER\Volatile Environment операционная система хранит динамические данные о текущем сеансе.

Там можно найти ключ RDP_CLIENT_ADDRESS, который содержит IP-адрес физического устройства пользователя. Разберем, как это можно использовать для более точной идентификации:


WshShell = Новый COMОбъект("Wscript.Shell");
// Получаем IP адрес клиента RDP
IPКлиента = WshShell.ExpandEnvironmentStrings("%RDP_CLIENT_ADDRESS%");
Если ЗначениеЗаполнено(IPКлиента) И IPКлиента <> "%RDP_CLIENT_ADDRESS%" Тогда
    Сообщить("IP-адрес терминала: " + IPКлиента);
КонецЕсли;

Особенности работы в Веб-клиенте

Нужно учитывать, что ни один из вышеперечисленных методов (кроме анализа сеансов на сервере) не будет работать в Веб-клиенте через браузер. Браузер работает в "песочнице" и не предоставляет 1С доступ к переменным окружения или COM-объектам операционной системы из соображений безопасности. В этом случае единственным надежным способом остается использование метода ПолучитьСеансыИнформационнойБазы() на стороне сервера, так как сервер 1С видит информацию о подключении даже через веб-протокол.

Заключение и рекомендации

Выбор метода зависит от ваших задач и прав доступа пользователей:

  1. Если у вас есть административные права или вы пишете служебный отчет для ИТ-отдела — используйте ПолучитьСеансыИнформационнойБазы(). Это самый надежный способ с точки зрения платформы.
  2. Если нужно решение для обычных пользователей — используйте чтение переменной %CLIENTNAME% через Wscript.Shell.
  3. Для универсальности в распределенных системах рекомендуется один раз при старте клиентского приложения определять имя компьютера и сохранять его в Параметры сеанса. Тогда в любой точке серверного кода вы сможете мгновенно получить имя терминала без лишних вычислений и запросов к ОС.

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

← На главную