К статье
Практический материал

Разработка и Конфигурация · 11 мин

1С: как передать COM-объект с клиента на сервер

Почему COM-объект нельзя передать с клиента на сервер 1С напрямую, какие есть рабочие обходные варианты: создание на сервере, передача данных, файловый обмен.

Задача передать COM-объект с клиента на сервер возникает у разработчиков 1С при интеграции с внешними системами: Excel, Word, базами через OLE DB, сторонними приложениями через V83.ComConnector. Ключевое ограничение нужно понять сразу: COM-объект — это ссылка на живой экземпляр внешнего приложения в памяти конкретного компьютера, и платформа 1С не умеет сериализовать такие объекты для передачи между клиентским и серверным процессами.

При попытке передать COM-объект параметром в серверный вызов вы получите ошибку вида «Ошибка передачи данных между клиентом и сервером» или «Недопустимый тип параметра». Это не баг конкретной конфигурации, а архитектурное ограничение: клиент и сервер 1С могут работать на разных машинах, и внешний процесс, к которому привязан COM-объект, физически существует только на одном из них.

Правильное решение — не пытаться «протащить» объект через границу клиент–сервер, а перестроить логику: либо создавать и использовать COM-объект целиком на одной стороне, либо передавать между сторонами только данные (строки, структуры, таблицы значений, двоичные данные). Ниже разобраны рабочие варианты и критерии выбора между ними.

Почему COM-объект нельзя передать между клиентом и сервером

Клиент-серверная архитектура 1С предполагает, что при вызове серверной процедуры все параметры сериализуются: преобразуются во внутренний формат, передаются по сети и восстанавливаются на другой стороне. Сериализации подлежат примитивные типы, структуры, массивы, таблицы значений, ссылки на объекты базы данных и ряд других типов платформы.

COM-объект (тип COMОбъект в языке 1С) — это обёртка над указателем на внешний процесс операционной системы. Указатель имеет смысл только в адресном пространстве того компьютера, где объект создан. Даже если бы платформа попыталась передать такой указатель, на сервере он указывал бы на несуществующую память, а само внешнее приложение (например, Excel) на сервере могло бы быть не установлено вовсе.

Дополнительное ограничение — модальность и контекст выполнения. В тонком и веб-клиенте COM-технология вообще недоступна на клиенте: COMОбъект работает только в толстом клиенте Windows. Поэтому код, завязанный на COM, чаще всего намеренно выносят на сервер или в фоновые задания.

Вариант 1: создавать COM-объект на сервере

Самый надёжный подход — перенести всю работу с COM на сервер. Клиент передаёт серверной процедуре только входные данные (путь к файлу, параметры подключения, строку подключения), сервер создаёт COMОбъект, выполняет операции и возвращает результат в сериализуемом виде.

&НаСервере

Функция ПрочитатьДанныеExcel(ПутьКФайлу)

Excel = Новый COMОбъект("Excel.Application");

Excel.Visible = Ложь;

Книга = Excel.Workbooks.Open(ПутьКФайлу);

Лист = Книга.Sheets(1);

Результат = Новый Массив;

Для Строка = 1 По Лист.UsedRange.Rows.Count Цикл

Результат.Добавить(Лист.Cells(Строка, 1).Value);

КонецЦикла;

Книга.Close(Ложь);

Excel.Quit();

Возврат Результат;

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

Обратите внимание на обязательное освобождение: вызов Quit() и завершение всех дочерних объектов. Если этого не сделать, процессы внешнего приложения будут накапливаться на сервере и со временем исчерпают память или дескрипторы — типичная причина «подвисаний» сервера 1С после интеграций с Excel.

Вариант 2: вся работа с COM на клиенте, на сервер — только данные

Если внешнее приложение установлено на компьютерах пользователей (типичный случай с Excel в толстом клиенте), логично оставить COM на клиенте. Клиент читает или записывает данные через COM-объект локально, а на сервер передаёт уже извлечённые значения: массивы, структуры, таблицы значений.

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

&НаКлиенте

Процедура ЗагрузитьНаКлиенте()

Excel = Новый COMОбъект("Excel.Application");

Книга = Excel.Workbooks.Open(ПутьКФайлу);

Данные = Новый Массив;

// ... чтение данных в массив структур ...

Книга.Close(Ложь);

Excel.Quit();

СохранитьДанныеНаСервере(Данные); // передаём только данные

КонецПроцедуры

Вариант 3: передача через файл и временное хранилище

Когда клиенту нужно отдать серверу содержимое файла для обработки COM-объектом на сервере, используется связка «временное хранилище + двоичные данные». Клиент помещает файл в хранилище, сервер извлекает его во временный файл и открывает COM-объектом уже локально на сервере.

Передача файла клиент → сервер для COM-обработки
  1. 1
    На клиенте вызовите НачатьПомещениеФайлаВХранилище или ПоместитьФайл и получите адрес временного хранилища
  2. 2
    Передайте адрес хранилища параметром в серверную процедуру
  3. 3
    На сервере получите двоичные данные: ПолучитьИзВременногоХранилища(Адрес)
  4. 4
    Запишите данные во временный файл на сервере (ПолучитьИмяВременногоФайла)
  5. 5
    Откройте файл COM-объектом, обработайте, закройте и удалите временный файл
  6. 6
    Верните результат клиенту в сериализуемом виде

Этот способ универсален: он работает и в тонком клиенте, и в веб-клиенте, потому что передача файла в хранилище — штатный механизм платформы, не требующий COM на клиенте. Не забудьте удалять временные файлы на сервере после обработки, иначе каталог временных файлов сервера будет расти.

Вариант 4: замена COM на альтернативные механизмы

Часто задача «передать COM-объект» на самом деле означает «обработать файл Excel/Word на сервере». Для этого COM может вообще не понадобиться:

  • ТабличныйДокумент.Прочитать() — платформа умеет читать файлы xlsx и mxl без установленного Excel, прямо на сервере;
  • Формат Open XML — разбор xlsx как zip-архива с XML через ЧтениеXML, работает в любом клиенте и на Linux-сервере;
  • Внешние компоненты (Native API) — подключаются и на клиенте, и на сервере, передаются между ними не компоненты, а их результаты;
  • HTTP и веб-сервисы — вместо COM-подключения к другой базе 1С используйте публикацию HTTP-сервисов или стандартный V83.ComConnector только на сервере.

Сравнение подходов

COM на сервере

Подходит для тонкого и веб-клиента; требует установки приложения и настройки DCOM на сервере, нагружает сервер

COM на клиенте

Подходит для толстого клиента с установленным приложением; не работает в тонком и веб-клиенте

Файл + временное хранилище

Универсально для всех клиентов; требует дисциплины очистки временных файлов

Отказ от COM (Open XML, ТабличныйДокумент)

Самый переносимый вариант, работает на Linux; покрывает не все сценарии, например сложные макросы Excel

Подключение к другой базе 1С через COM: где выполнять

Отдельный частый случай — COMObject("V83.COMConnector") для подключения к другой информационной базе. Здесь действует то же правило: объект подключения нельзя вернуть с сервера на клиент или наоборот. Каждая сторона, которой нужно подключение, создаёт его сама.

Рекомендуемая практика — выполнять COM-подключения к внешним базам только на сервере, желательно в фоновом задании. Тогда обмен не блокирует интерфейс пользователя, а строка подключения и пароль не попадают в клиентский код, где их легко извлечь.

bsl
&НаСервере
Функция ПолучитьДанныеИзВнешнейБазы(СтрокаПодключения)
    Коннектор = Новый COMОбъект("V83.COMConnector");
    Соединение = Коннектор.Connect(СтрокаПодключения);
    Запрос = Соединение.NewObject("Запрос");
    // ... выполнение запроса, выгрузка в таблицу значений ...
    Возврат РезультатТЗ; // передаём только данные
КонецФункции

Типичные ошибки и как их диагностировать

Первая ошибка — попытка вернуть COMОбъект из серверной функции. Платформа выдаст ошибку сериализации ещё на этапе вызова. Признак: сообщение о недопустимом типе параметра или значении возврата. Решение — возвращать данные, а не объект.

Вторая ошибка — создание COM-объекта в общем модуле с флагами «Клиент» и «Сервер» без разделения контекста. Код компилируется, но падает в тонком клиенте. Используйте директивы #Если ТолстыйКлиентОбычноеПриложение или явно разделяйте модули.

Третья ошибка — утечка процессов: Excel.Quit() не вызывается при исключении. Оборачивайте работу с COM в Попытка/Исключение с гарантированным завершением в блоке, который выполнится всегда, либо явно освобождайте объект в обработчике исключения.

Типичные ошибки
01
Возврат COMОбъекта из серверной функции — ошибка сериализации при вызове
02
Использование COM в тонком или веб-клиенте — объект недоступен, код падает
03
Отсутствие Quit() при исключении — накопление зависших процессов внешнего приложения на сервере
04
Передача всего файла данными через параметры вместо временного хранилища — лишний расход памяти
05
Хранение строки подключения с паролем в клиентском коде — компрометация доступа к внешней базе

Как проверить результат

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

Контрольные точки

Контрольные точки

Вызов серверной процедуры
Норма

Выполняется без ошибок передачи данных

Тревожный признак

Ошибка о недопустимом типе параметра или значения

Процессы внешнего приложения на сервере
Норма

Завершаются после каждой операции

Тревожный признак

Процессы накапливаются, растёт потребление памяти

Временные файлы на сервере
Норма

Удаляются после обработки

Тревожный признак

Каталог временных файлов постоянно растёт

Работа в тонком клиенте
Норма

Функциональность доступна, COM только на сервере

Тревожный признак

Ошибка создания COMОбъект на клиенте

FAQ

Можно ли передать COM-объект через параметр сеанса или реквизит формы?

Нет. Параметры сеанса и реквизиты формы подчиняются тем же правилам сериализации при передаче между клиентом и сервером. COMОбъект нельзя сохранить ни в одном механизме, предполагающем перенос данных между контекстами.

Работает ли COMОбъект на сервере под Linux?

Нет, COM — технология Windows. На Linux-сервере для работы с файлами Excel используйте ТабличныйДокумент.Прочитать или разбор Open XML, а для подключения к другим базам — HTTP-сервисы вместо V83.COMConnector.

Почему COM-подключение к другой базе работает на клиенте, но не на сервере?

Чаще всего дело в разрядности и учётной записи: на сервере должен быть зарегистрирован V83.COMConnector той же разрядности, что и рабочий процесс сервера, а учётная запись службы агента должна иметь сетевой доступ к серверу внешней базы.

Как передать на сервер большую таблицу, прочитанную через Excel на клиенте?

Передавайте таблицу значений или массив структур порциями, либо сохраните данные в промежуточный формат (например, mxl или csv) и передайте файл через временное хранилище — это надёжнее при объёмах в десятки тысяч строк.

Нужно ли освобождать COM-объект явно, если процедура завершилась без ошибок?

Да. Сборщик мусора платформы не управляет внешними процессами. Всегда вызывайте методы завершения (Quit, Close) и присваивайте переменной Неопределено, особенно в серверном коде, где зависший процесс влияет на всех пользователей.

Итог

Что важно запомнить

COM-объект нельзя передать между клиентом и сервером 1С — это архитектурное ограничение. Создавайте COM-объект на той стороне, где он используется, передавайте между сторонами только данные и файлы через временное хранилище, всегда освобождайте внешние процессы и по возможности заменяйте COM на переносимые механизмы платформы.