При работе с торговым оборудованием в среде удаленных рабочих столов (RDP) часто возникает неприятная ситуация: внешняя обработка успешно подключает сканер, всё работает, но после закрытия формы порт остается «зависшим». При повторном открытии обработки или попытке другого пользователя подключиться к оборудованию 1С выдает ошибку «Порт занят». Особенно остро эта проблема проявляется на серверах под управлением Windows Server 2008 и при использовании устаревших библиотек типа scanopos.dll.
В этой статье мы подробно разберем, почему возникает эта ошибка, и рассмотрим пошаговые методы очистки ресурсов и правильного отключения оборудования.
Проанализируем ситуацию. В локальном режиме (на физической машине) драйвер обычно корректно освобождает COM-порт при уничтожении объекта. Однако в терминальной сессии (RDP) используется механизм перенаправления портов (COM-mapping). Когда 1С закрывает объект, терминальная служба может продолжать удерживать дескриптор (handle) виртуального порта, считая сессию активной. Если сервер виртуализирован (Hyper-V или VMware), ситуация усугубляется за счет дополнительных уровней абстракции USB-контроллера.
Одной установки Сканер = Неопределено; часто бывает недостаточно, так как COM-объект может оставаться в памяти из-за счетчика ссылок. Нам необходимо принудительно дать команду драйверу освободить устройство. Рассмотрим правильный алгоритм в процедуре ПриЗакрытии или ПередЗакрытием формы:
Процедура ПриЗакрытии()
Если ОбъектСканер <> Неопределено Тогда
Попытка
// 1. Сначала отключаем само устройство на уровне драйвера
ОбъектСканер.DeviceEnabled = 0; // Или Ложь, в зависимости от версии драйвера
// 2. Если используется старый драйвер Атол или ScanOPOS,
// иногда требуется перевести в режим OldVersion
// ОбъектСканер.OldVersion = 0;
// 3. Обнуляем ссылку на объект
ОбъектСканер = Неопределено;
Исключение
Сообщить("Ошибка при отключении сканера: " + ОписаниеОшибки());
КонецПопытки;
КонецЕсли;
КонецПроцедуры
Важный момент: если вы используете драйверы «Атол» старых версий (например, 6.х или 8.х), убедитесь, что в вашей версии нет метода Done(). Если он есть, его вызов перед обнулением объекта обязателен.
Библиотеки scanopos.dll и scaner1c.dll используют технологию COM, которая в современных операционных системах считается устаревшей и нестабильной в RDP-среде. Мы рекомендуем перейти на использование Native API компоненты от 1С (1C:BarCodeScanner).
Преимущества Native API:
Для перехода проанализируем настройки торгового оборудования в вашей конфигурации. Если это «Управление торговлей 10.3», попробуйте обновить обработку обслуживания до последней версии, поддерживающей NativeApi.
Если код корректен, но проблема сохраняется на Windows Server 2008, выясним, не блокирует ли порт сама служба RDS. Проанализируем настройки подключения в конфигурации RDP-клиента:
mstsc.exe и использовать сторонние утилиты для проброса USB (например, USB-over-Network).Чтобы точно понять, какой процесс держит порт, воспользуемся системной утилитой Handle от Sysinternals. Запустите ее в командной строке на сервере:
handle.exe \Device\Serial
Проанализируем вывод. Если вы видите, что дескриптор порта удерживается процессом 1cv8.exe даже после закрытия обработки, значит, объект COM все еще «жив» в памяти. Если же порт держит системный процесс или rdpclip.exe, проблема на уровне операционной системы.
Если борьба с виртуальными COM-портами в RDP не приносит успеха, рассмотрим вариант перевода сканера в режим Keyboard Emulation. В этом режиме сканер не занимает порт, а передает данные как обычный ввод с клавиатуры. Для 1С это потребует использования префиксов (например, # или F7), чтобы программа понимала, что ввод пришел со сканера, а не от пользователя.
Резюмируем: для стабильной работы в RDP на Windows Server 2008 лучше всего отказаться от старых COM-компонент в пользу Native API. Если это невозможно — всегда явно устанавливайте DeviceEnabled = 0 перед уничтожением объекта в 1С.