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

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

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

В данной статье мы подробно разберем, как реализовать подобный функционал. Мы изучим базовый метод, предложенный на форуме, проанализируем его критические недостатки, разберем причины сбоев при работе с несколькими серверами и рассмотрим альтернативные, более безопасные и профессиональные варианты интеграции RDP в 1С.

---

Способ 1. Использование системных утилит cmdkey и mstsc (Базовый метод)

Самый простой и быстрый способ запустить удаленный рабочий стол из 1С — использовать стандартный клиент Windows Terminal Services (mstsc.exe) совместно с утилитой управления учетными данными (cmdkey.exe). Дело в том, что сам по себе исполняемый файл mstsc.exe из соображений безопасности не поддерживает прямую передачу пароля через параметры командной строки. Чтобы обойти это ограничение, мы сначала регистрируем учетные данные в системе под текущим пользователем Windows, а затем инициализируем подключение.

Разберем по шагам, как это реализовать в коде 1С. Нам понадобятся три параметра: адрес сервера (или IP), имя пользователя и пароль.


&НаКлиенте
Процедура ПодключитьсяКУдаленномуСтолу(АдресСервера, Пользователь, Пароль)
    
    // Шаг 1. Регистрируем учетные данные в Диспетчере учетных данных Windows
    ШаблонКомандыАвторизации = "cmdkey /generic:""%1"" /user:""%2"" /pass:""%3""";
    КомандаАвторизации = СтрШаблон(ШаблонКомандыАвторизации, АдресСервера, Пользователь, Пароль);
    
    // Запускаем cmdkey в скрытом режиме и ждем завершения выполнения
    ЗапуститьПриложение(КомандаАвторизации, , Истина);
    
    // Шаг 2. Запускаем стандартный RDP-клиент Windows
    ШаблонКомандыЗапуска = "mstsc /v:""%1""";
    КомандаЗапуска = СтрШаблон(ШаблонКомандыЗапуска, АдресСервера);
    
    // Запускаем mstsc без ожидания, чтобы окно 1С не блокировалось
    ЗапуститьПриложение(КомандаЗапуска, , Ложь);
    
КонецПроцедуры

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

---

Анализ проблемы: Почему не удается подключиться ко второму серверу?

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

Утилита cmdkey осуществляет привязку сохраненных данных к сетевому имени хоста (параметр /generic). Если ваши удаленные серверы находятся за одним внешним статическим IP-адресом и различаются только номерами портов (например, 192.168.1.10:3389 и 192.168.1.10:3390), то операционная система Windows воспринимает их как один и тот же сетевой узел. Повторный вызов команды cmdkey для этого же IP-адреса просто перезаписывает сохраненные данные авторизации в Диспетчере учетных данных (Windows Credential Manager). В итоге активное или новое подключение завершается сбоем.

Как решить эту проблему?

  1. Использование уникальных доменных имен (DNS-алиасов). Вместо обращения по IP-адресам настройте для серверов уникальные имена на вашем DNS-сервере или пропишите их локально в файле hosts на клиентском компьютере (например, buh-server, sklad-server). В таком случае cmdkey будет создавать разные записи в хранилище для каждого уникального имени.
  2. Динамическая очистка учетных записей. Сразу после того как окно RDP-сессии успешно инициализировано, рекомендуется удалять учетные данные из хранилища. Это решает и проблему конфликта имен, и проблему безопасности.

---

Критическая уязвимость метода cmdkey и ее устранение

Использование cmdkey несет в себе скрытую и очень серьезную угрозу безопасности. Когда вы выполняете данную команду, пароль пользователя сохраняется в системе на постоянной основе. Это означает, что любой человек, получивший доступ к вашему физическому рабочему месту (или запустивший команду из-под вашей учетной записи), может запустить mstsc и беспрепятственно войти на удаленный сервер без ввода пароля, поскольку Windows автоматически подставит ранее сохраненный ключ.

Чтобы обезопасить систему, необходимо в обязательном порядке выполнять очистку сохраненных учетных данных. Рассмотрим доработанную схему запуска, которая удаляет следы авторизации:


&НаКлиенте
Процедура БезопасныйЗапускRDP(АдресСервера, Пользователь, Пароль)
    
    // Записываем учетные данные
    КомандаЗаписи = СтрШаблон("cmdkey /generic:""%1"" /user:""%2"" /pass:""%3""", АдресСервера, Пользователь, Пароль);
    ЗапуститьПриложение(КомандаЗаписи, , Истина);
    
    // Запускаем RDP
    КомандаЗапуска = СтрШаблон("mstsc /v:""%1""", АдресСервера);
    ЗапуститьПриложение(КомандаЗапуска, , Ложь);
    
    // Делаем небольшую паузу, чтобы служба RDP успела считать кэш
    ПодключитьОбработчикОжидания("ВыполнитьОчисткуКлюча", 3, Истина);
    
    // Сохраняем адрес сервера для обработчика очистки во временной переменной или реквизите формы
    ПараметрОчисткиАдрес = АдресСервера;
    
КонецПроцедуры

&НаКлиенте
Процедура ВыполнитьОчисткуКлюча()
    
    // Удаляем данные из Диспетчера учетных данных Windows
    КомандаОчистки = СтрШаблон("cmdkey /delete:""%1""", ПараметрОчисткиАдрес);
    ЗапуститьПриложение(КомандаОчистки, , Истина);
    
КонецПроцедуры

Использование обработчика ожидания позволяет сделать паузу в несколько секунд. Этого времени вполне достаточно, чтобы процесс mstsc.exe обратился к Диспетчеру учетных данных и прошел фазу авторизации на удаленном сервере. Сразу после этого учетная запись удаляется с клиентской машины, предотвращая несанкционированный доступ в будущем.

---

Способ 2. Программная генерация файлов .rdp

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

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

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

Рассмотрим по шагам реализацию данного метода:


&НаКлиенте
Процедура СоздатьИЗапуститьRDPФайл(АдресСервера, Логин, Пароль)
    
    ПутьКФайлуRDP = КаталогВременныхФайлов() + "temp_connection.rdp";
    
    // 1. Формируем базовые настройки RDP-файла
    ТекстФайла = Новый ТекстовыйДокумент;
    ТекстФайла.ДобавитьСтроку("screen mode id:i:2"); // Открывать во весь экран
    ТекстФайла.ДобавитьСтроку(СтрШаблон("full address:s:%1", АдресСервера));
    ТекстФайла.ДобавитьСтроку(СтрШаблон("username:s:%1", Логин));
    ТекстФайла.ДобавитьСтроку("redirectdrives:i:1"); // Пробросить локальные диски
    ТекстФайла.ДобавитьСтроку("redirectclipboard:i:1"); // Включить буфер обмена
    
    // Записываем временный файл без пароля
    ТекстФайла.Записать(ПутьКФайлуRDP, КодировкаТекста.ANSI);
    
    // 2. Шифруем пароль через PowerShell и дописываем его в файл
    // Алгоритм шифрования использует DPAPI текущего пользователя Windows
    СкриптШифрования = "[system.security.cryptography.protecteddata]::Protect(" + 
                       "[system.text.encoding]::Unicode.GetBytes('" + Пароль + "'), $null, " + 
                       "[system.security.cryptography.datacapability]::UserOnly)";
                       
    КомандаPS = "powershell -Command ""$bytes = " + СкриптШифрования + "; " +
                "$hash = [System.BitConverter]::ToString($bytes).Replace('-', ''); " +
                "Add-Content '" + ПутьКФайлуRDP + "' -Value ('password 51:b:' + $hash)""";
                
    // Выполняем скрипт шифрования
    ЗапуститьПриложение(КомандаPS, , Истина);
    
    // 3. Запускаем сессию
    ЗапуститьПриложение(ПутьКФайлуRDP, , Ложь);
    
КонецПроцедуры

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

---

Способ 3. Встраивание RDP прямо в форму 1С

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

Для реализации этого метода используется элемент управления ActiveX — библиотека Microsoft RDP Client Control (компонента mstscax.dll, стандартно поставляемая с Windows).

Реализация в Обычных формах (1С 8.2)

В толстом клиенте на обычную форму можно напрямую добавить элемент управления ActiveX. Для этого при редактировании формы выберите пункт меню "Форма" -> "Вставить элемент управления" и в появившемся списке найдите Microsoft RDP Client Control.

Проанализируем пример программного управления этим объектом:


// Пример кода для обычной формы при открытии
Процедура ПриОткрытии()
    
    Попытка
        // Элементы.RDPControl - имя добавленного ActiveX элемента на форме
        РДП = Элементы.RDPControl;
        РДП.Server = "192.168.1.100";
        РДП.UserName = "Administrator";
        
        // Передача пароля в открытом виде разрешена свойствами этого ActiveX
        РДП.AdvancedSettings2.ClearTextPassword = "MyPassword123";
        
        // Запуск соединения
        РДП.Connect();
    Исключение
        Предупреждение("Не удалось инициализировать RDP ActiveX компоненту!");
    КонецПопытки;
    
КонецПроцедуры

Реализация в Управляемых формах (1С 8.3)

Платформа 1С v8.3 на управляемых формах напрямую не поддерживает размещение ActiveX элементов. Тем не менее, эту проблему можно элегантно решить с помощью элемента формы Поле HTML документа. Мы можем сгенерировать HTML-код, содержащий вызов объекта ActiveX через тег <object>, и передать его в это поле.

Рассмотрим пример генерации такого HTML-кода:


&НаСервере
Функция ПолучитьHTMLКодRDP(Сервер, Логин, Пароль) Экспорт

    ШаблонHTML = 
    "<html>
    |<head>
    |<script type='text/javascript'>
    |   function Connect() {
    |       try {
    |           var rdp = document.getElementById('RdpClient');
    |           rdp.Server = '%1';
    |           rdp.UserName = '%2';
    |           rdp.AdvancedSettings2.ClearTextPassword = '%3';
    |           rdp.Connect();
    |       } catch(e) {
    |           alert('Ошибка подключения: ' + e.message);
    |       }
    |   }
    |</script>
    |</head>
    |<body onload='Connect();' style='margin:0px; padding:0px; overflow:hidden;'>
    |   <object id='RdpClient' 
    |       classid='CLSID:4eb2f286-3119-43a5-85d3-e711ea61d8b3' 
    |       width='100%' 
    |       height='100%'>
    |   </object>
    |</body>
    |</html>";
    
    Возврат СтрШаблон(ШаблонHTML, Сервер, Логин, Пароль);

КонецФункции

Полученный HTML-текст записывается в реквизит управляемой формы, связанный с Полем HTML документа. При загрузке страницы JavaScript-код автоматически инициализирует подключение к удаленному рабочему столу прямо внутри рабочего пространства 1С.

Важное ограничение: Данный метод работоспособен только в среде операционной системы Windows и требует соответствующих настроек безопасности в локальных политиках или браузере Internet Explorer (разрешение на запуск элементов ActiveX, не помеченных как безопасные).

---

Сравнение методов подключения

Для того чтобы вам было проще определиться с выбором архитектуры решения, сопоставим рассмотренные методы по ключевым критериям:

  1. Метод cmdkey + mstsc:
    • Сложность реализации: Очень низкая.
    • Безопасность: Низкая (требуется обязательное ручное удаление паролей из хранилища Windows).
    • Гибкость настроек: Средняя (ограничена базовыми параметрами запуска mstsc).
    • Удобство пользователя: Открывается отдельное окно Windows.
  2. Генерация файлов .rdp:
    • Сложность реализации: Средняя (требуется шифрование через PowerShell / DPAPI).
    • Безопасность: Высокая (пароли хранятся в зашифрованном виде, привязанном к текущему пользователю).
    • Гибкость настроек: Очень высокая (доступны любые параметры RDP-протокола).
    • Удобство пользователя: Открывается отдельное окно Windows.
  3. Встраивание через ActiveX/HTML:
    • Сложность реализации: Высокая.
    • Безопасность: Средняя (пароль передается в коде HTML/JS страницы).
    • Гибкость настроек: Высокая.
    • Удобство пользователя: Максимальное (работа в бесшовном режиме "одного окна" внутри 1С).

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

← На главную