Почему перестал работать COM-объект после перехода на 1С:Сервер Мини и как это исправить?

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

Переход с файлового режима работы 1С на клиент-серверный вариант (особенно при использовании 1С:Сервер Мини) часто сопровождается техническими сложностями, которые не проявлялись ранее. Одной из самых острых проблем является внезапный отказ работы внешних библиотек через механизм COMObject. В файловом режиме код выполняется в контексте текущего пользователя Windows, а в серверном — контекст и права резко меняются. Рассмотрим подробно, почему это происходит и как реанимировать связь с внешним оборудованием (на примере весового терминала «Весовая 4.3» от НАИС).

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

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


&НаСервере
Процедура ПолучитьВесБруттоНаСервере()
    Попытка
        WeightRoom43 = Новый COMObject("WeightRoom43.WeightRoom"); 
        // Дальнейшая работа с объектом
    Исключение
        Сообщить("Не удалось подключиться к ПО Весовая!");
    КонецПопытки;
КонецПроцедуры

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

  1. Разрядность процессов (x86 против x64). Если сервер 1С установлен как 64-битное приложение, а библиотека WeightRoom43.dll является 32-битной, прямой вызов Новый COMObject завершится неудачей. Процесс rphost (64 бит) не может загрузить в свою память 32-битную DLL.
  2. Контекст исполнения и права доступа. Серверная служба 1С обычно работает под учетной записью usr1cv8. У этой записи нет прав на запуск интерактивных приложений, доступ к рабочему столу или специфическим веткам реестра HKEY_CLASSES_ROOT, где зарегистрирована библиотека.
  3. Физическое отсутствие библиотеки. В файловом режиме всё работало, так как библиотека была зарегистрирована на локальном ПК. После переноса кода на сервер необходимо убедиться, что ПО «Весовая» или соответствующая DLL установлена и зарегистрирована именно на серверной машине.

Решение №1: Использование COM+ (Wrapper для 32-битных компонент)

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

Для этого выполним следующие действия на сервере:

  1. Откроем Панель управления -> Администрирование -> Службы компонентов.
  2. Перейдем в ветку Компьютеры -> Мой компьютер -> Приложения COM+.
  3. Создадим новое приложение (Правой кнопкой -> Создать -> Приложение). Выберем "Создать новое приложение", введем имя (например, 1C_Weight_Link) и выберем тип "Серверное приложение".
  4. В качестве учетной записи укажем пользователя, от имени которого работает сервер 1С (обычно usr1cv8), либо интерактивного пользователя (если драйвер требует GUI).
  5. В созданном приложении перейдем в папку Компоненты и добавим нашу библиотеку (указав путь к WeightRoom43.dll или выбрав её из списка зарегистрированных).

Этот метод заставит Windows запускать библиотеку в отдельном процессе dllhost.exe, который будет выступать посредником между 64-битной 1С и 32-битной компонентой.

Решение №2: Перенос кода на сторону клиента

Как справедливо отмечают эксперты на форумах, работа с торговым и весовым оборудованием — это прерогатива клиентского приложения. Рассмотрим подробнее, почему это лучший вариант. Оборудование (весы, камеры) чаще всего подключено к конкретному рабочему месту. Пытаться дергать COM-порт или USB-устройство из серверного процесса, который может находиться в другой комнате или даже в другом дата-центре — архитектурная ошибка.

Проанализируем правильный подход к изменению кода. Вместо вызова &НаСервере, мы должны инициализировать объект непосредственно в контексте &НаКлиенте:


&НаКлиенте
Процедура ПолучитьВесТары(Команда)
    Попытка
        // Инициализируем объект прямо на клиенте
        WeightRoom43 = Новый COMObject("WeightRoom43.WeightRoom");
        
        // Получаем данные
        Вес = WeightRoom43.ReadWeight(1);
        
        // Передаем данные на сервер для записи в БД
        ЗаписатьВесНаСервере(Вес);
        
        // Работаем с фото (пути должны быть доступны клиенту)
        Путь1 = "\\WEIGHTROOM2\Pictures\TTN_" + Объект.НомерТТН + "_1.bmp";
        WeightRoom43.GetFoto("1", Путь1);
    Исключение
        Сообщить("Ошибка подключения к весам на локальном ПК: " + ОписаниеОшибки());
    КонецПопытки;
КонецПроцедуры

Важный нюанс: при переносе кода на клиент убедитесь, что на каждом рабочем месте, где будет нажиматься кнопка «Получить вес», установлена и зарегистрирована библиотека WeightRoom43.dll. Сделать это можно командой: regsvr32 "C:\Path\To\WeightRoom43.dll" от имени администратора.

Решение №3: Настройка отладки на сервере

Часто программисты жалуются: «Точка останова не срабатывает, объект пустой». Это происходит потому, что в клиент-серверном варианте отладка на сервере по умолчанию отключена. Выясним, как проверить работу COMObject под отладчиком.

Для активации отладки выполним следующие действия:

  1. Остановим службу 1C:Enterprise 8.3 Server Agent.
  2. В реестре Windows найдем ветку службы (обычно HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\1CV8...).
  3. В параметре ImagePath добавим в конец строки ключ -debug.
  4. Запустим службу заново.

Теперь точка останова внутри процедуры &НаСервере будет срабатывать, и вы сможете увидеть реальную причину ошибки при создании объекта (например, "Класс не зарегистрирован" или "Отказ в доступе").

Проблема прав доступа к сетевым ресурсам (UNC-пути)

Разберем ситуацию с сохранением фотографий. В коде автора используются пути вида \\WEIGHTROOM2\Pictures\. При работе на сервере важно понимать: сетевые диски (Z:, Y:) серверу 1С не видны. Нужно использовать только полные UNC-пути.

Более того, если код выполняется &НаСервере, то у пользователя usr1cv8 должны быть полные права (Чтение/Запись) на сетевую папку Pictures на сервере WEIGHTROOM2. Если прав нет, метод WeightRoom43.GetFoto() либо вернет ошибку, либо просто не создаст файл, что приведет к пустым реквизитам в 1С.

Итоги и рекомендации

Подводя итог, можно составить краткий чек-лист для исправления работы COM-объектов при переходе на сервер:

Используя эти методы, вы сможете стабильно интегрировать 1С с любым внешним ПО, работающим через COM-интерфейс, независимо от режима работы платформы.

← На главную