Как отправить команду на устройство через Telnet из 1С?

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

При интеграции 1С с торговым или промышленным оборудованием (принтеры этикеток, весы, контроллеры) часто возникает необходимость передать управляющую команду по протоколу Telnet. Однако стандартный клиент Windows telnet.exe не предназначен для автоматизации и часто вызывает ошибки при вызове из кода 1С. В этой статье мы подробно разберем, почему возникает ошибка «Не удается найти указанный файл», как ее обойти и какие современные альтернативы лучше использовать для стабильной работы.

Причина ошибки «Не удается найти указанный файл»

Рассмотрим типичную ситуацию: вы проверяете наличие файла по пути C:\Windows\System32\telnet.exe, он там есть, но при вызове через WshShell.Exec или КомандаСистемы программа 1С выдает ошибку. Проанализируем причину этого явления.

Дело в том, что большинство дистрибутивов 1С являются 32-битными приложениями. В 64-битных версиях Windows реализован механизм FS Redirector (перенаправление файловой системы). Когда 32-битная программа обращается к папке System32, операционная система прозрачно для пользователя перенаправляет запрос в папку C:\Windows\SysWOW64. Поскольку утилита telnet.exe является системным компонентом и часто отсутствует в SysWOW64, 1С ее «не видит».

Чтобы решить эту проблему, следует использовать специальный виртуальный путь Sysnative, который позволяет 32-битным приложениям обращаться к реальной папке System32. Исправленный код вызова будет выглядеть так:


// Использование Sysnative для обхода редиректора файловой системы
ПутьКТелнету = "C:\Windows\Sysnative\telnet.exe";
objShell = Новый COMОбъект("WScript.Shell");
Попытка
    objScriptExec = objShell.Exec(ПутьКТелнету + " 192.168.102.2");
Исключение
    Сообщить("Ошибка запуска: " + ОписаниеОшибки());
КонецПопытки;

Проблема интерактивности стандартного Telnet

Даже если файл успешно запущен, возникает вторая проблема: стандартный telnet.exe в Windows — это интерактивная утилита. Она ожидает ввода пользователя с клавиатуры и не принимает команды через перенаправление потока данных (например, через символ | или <). Попытки использовать SendKeys для имитации нажатий клавиш крайне ненадежны, так как любая задержка сети или смена фокуса окна приведет к потере данных.

Разберем более надежные способы решения задачи.

Решение №1: Использование утилиты Plink (PuTTY)

Одним из самых стабильных решений является использование консольного клиента Plink (часть пакета PuTTY). В отличие от системного телнета, Plink отлично поддерживает автоматизацию и позволяет отправить команду одной строкой.

Рассмотрим пример отправки команды 12345 на устройство:


// Пример использования plink.exe
// -telnet указывает протокол
// -batch отключает интерактивные запросы
КомандаЗапуска = "C:\Tools\plink.exe -telnet -batch 192.168.102.2 -P 4001";
ТекстКоманды = "12345";

// Используем временный файл для передачи команды в поток stdin
ИмяФайлаСкрипта = ПолучитьИмяВременногоФайла("txt");
ТекстовыйДокумент = Новый ТекстовыйДокумент;
ТекстовыйДокумент.УстановитьТекст(ТекстКоманды);
ТекстовыйДокумент.Записать(ИмяФайлаСкрипта, КодировкаТекста.ANSI);

ПолнаяКоманда = "cmd /c type " + ИмяФайлаСкрипта + " | " + КомандаЗапуска;
ЗапуститьПриложение(ПолнаяКоманда, , Истина); // Ждем завершения

Решение №2: Использование PowerShell (без сторонних утилит)

Если на сервере или компьютере пользователя нельзя устанавливать стороннее ПО, можно воспользоваться мощью PowerShell, который встроен в современные версии Windows. Мы можем создать TCP-соединение напрямую и отправить данные в сокет. Это наиболее «чистый» способ с точки зрения системного администрирования.

Проанализируем алгоритм: мы создаем объект TcpClient, открываем поток и записываем в него наши данные. Весь этот скрипт можно упаковать в одну строку и вызвать из 1С.


Функция ОтправитьКомандуЧерезPowerShell(IPАдрес, Порт, Команда)
    // Формируем скрипт PowerShell
    Скрипт = "$socket = New-Object System.Net.Sockets.TcpClient('" + IPАдрес + "', " + Порт + "); " +
             "$stream = $socket.GetStream(); " +
             "$writer = New-Object System.IO.StreamWriter($stream); " +
             "$writer.WriteLine('" + Команда + "'); " +
             "$writer.Flush(); " +
             "$socket.Close();";
    
    // Запускаем PowerShell с подавлением окна
    КомандаВыполнения = "powershell -NoProfile -ExecutionPolicy Bypass -Command """ + Скрипт + """";
    ЗапуститьПриложение(КомандаВыполнения, , Истина);
КонецФункции

Решение №3: Использование cURL

В последних обновлениях Windows 10 и в Windows 11 утилита cURL встроена в систему по умолчанию. Она поддерживает протокол Telnet. Хотя для сложных интерактивных сессий она подходит меньше, для простой отправки «плевков» данных она может быть полезна.

Команда в консоли выглядит следующим образом: curl telnet://192.168.102.2:4001. Однако стоит учитывать, что cURL может ожидать ручного закрытия сессии, поэтому для автоматизации из 1С метод с PowerShell остается более предпочтительным.

Решение №4: Прямая печать (RAW) на порт 9100

Выясним важную деталь: если ваше устройство — это сетевой принтер, то зачастую использование Telnet избыточно. Большинство принтеров поддерживают RAW-протокол на порту 9100. Если ваша задача — просто отправить последовательность байтов, вы можете отправить файл напрямую на IP-адрес принтера.

В Windows это можно сделать через команду print или просто скопировав файл в сетевой порт, если принтер установлен в системе. Если принтер не установлен, можно использовать утилиту nc (Netcat) для Windows:

echo 12345 | nc -w 1 192.168.102.2 9100

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

  1. Проверка прав: При запуске внешних приложений из 1С (особенно в серверном варианте) убедитесь, что у пользователя, под которым запущен кластер 1С, есть права на выполнение командной строки и доступ к соответствующим исполняемым файлам.
  2. Кодировки: При отправке команд на оборудование крайне важно соблюдать кодировку. Большинство старых устройств понимают только ANSI или IBM866. При записи временных файлов в 1С всегда явно указывайте кодировку.
  3. Таймауты: При работе с сетевыми устройствами всегда закладывайте время на установку соединения. В примере с PowerShell или Plink соединение может не установиться мгновенно, поэтому при необходимости получения ответа используйте паузы (Sleep).

Подведем итог: для разовой отправки простой команды на устройство лучшим выбором будет использование PowerShell через ЗапуститьПриложение, так как это не требует внешних библиотек и легко отлаживается. Если же требуется сложный обмен данными с обработкой ответов от устройства, стоит рассмотреть написание или использование готовой Внешней компоненты (Native API) для работы с TCP/IP напрямую.

← На главную