Как вызвать клиентский метод из модуля менеджера и распечатать документ с использованием внешнего приложения?

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

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

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

Суть проблемы: почему сервер "не видит" клиента?

Давайте проанализируем исходную ситуацию. Разработчик пытается использовать метод ЗапуститьПриложение() внутри модуля менеджера объекта.

Почему это не работает так, как ожидается?

  1. Разделение контекстов: Модуль менеджера компилируется и выполняется исключительно на сервере.
  2. Изоляция: Сервер 1С ничего не знает о файловой системе локального компьютера пользователя (клиента). Когда вы передаете путь к файлу или программе в метод ЗапуститьПриложение() на сервере, система ищет этот путь на серверной машине, а не на вашем ПК.
  3. Инициатива соединения: В архитектуре 1С сервер не может самостоятельно "постучаться" к клиенту и сказать: "Выполни этот код". Только клиент может отправить запрос серверу и ждать ответа.

Именно поэтому попытки вызвать клиентскую процедуру напрямую или получить форму (ПолучитьФорму()) из модуля менеджера обречены на неудачу — этих объектов в памяти сервера просто не существует.

Решение 1: Правильное использование БСП (Библиотека Стандартных Подсистем)

Если ваша конфигурация построена на базе БСП (а это большинство современных типовых решений, таких как ERP, УТ, КА, БП), то "велосипеды" изобретать не нужно. Разработчики библиотеки уже предусмотрели механизм для выполнения кода на клиенте при печати.

Обычно команды печати регистрируются в процедуре ДобавитьКомандыПечати в модуле менеджера. По умолчанию они выполняются на сервере. Однако, мы можем изменить это поведение.

Давайте рассмотрим, как правильно настроить команду, чтобы она передавала управление на клиент:


// В модуле менеджера документа
Процедура ДобавитьКомандыПечати(КомандыПечати) Экспорт
    
    // Добавляем новую команду
    Команда = КомандыПечати.Добавить();
    Команда.Идентификатор = "ПечатьКартинкиPDF";
    Команда.Представление = "Печать PDF как картинки";
    
    // САМОЕ ВАЖНОЕ: Меняем тип команды
    // Стандартно там "ВызовСерверногоМетода", нам нужен клиент
    Команда.ТипКоманды = "ВызовКлиентскогоМетода"; 
    
    // Указываем путь к клиентскому общему модулю или модулю формы внешней обработки
    Команда.МенеджерПечати = "НашОбщийМодульПечатиКлиент"; 
    
КонецПроцедуры

Теперь, когда пользователь нажмет кнопку "Печать", БСП не будет пытаться выполнить процедуру Печать в модуле менеджера. Вместо этого, она вызовет экспортную процедуру Печать из указанного вами клиентского общего модуля (НашОбщийМодульПечатиКлиент).

А уже внутри клиентского модуля вы имеете полное право использовать:

Решение 2: Перенос инструментов на сервер

Если задача подразумевает массовую печать, фоновое выполнение или вы не хотите зависеть от того, установлен ли какой-то конвертер (например, ImageMagick) на компьютере каждого бухгалтера, правильнее будет перенести логику на сервер.

Рассмотрим этот подход:

  1. Установка ПО: Вы устанавливаете необходимые утилиты (ImageMagick, GhostScript) непосредственно на сервер, где работает служба 1С (или веб-сервер).
  2. Настройка прав: Учетной записи, под которой запущена служба сервера 1С (обычно USR1CV8), необходимо дать права на чтение и выполнение файлов в папке с утилитами.
  3. Код в модуле менеджера: Вы оставляете код в модуле менеджера, но пути к программам указываете серверные.

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

Пример серверного вызова (синхронный вариант для сервера допустим, но лучше использовать объекты ЗапускПриложения):


// Код выполняется НаСервере
ЗапуститьПриложение("C:\ServerTools\ImageMagick\convert.exe " + ПараметрыКонвертации, , Истина);

Решение 3: Использование внешних компонент (Native API)

Чтобы избежать запуска внешних EXE-файлов (что не всегда безопасно и удобно отлаживать), можно воспользоваться внешними компонентами (AddIn), созданными по технологии Native API.

Существуют компоненты (многие из них с открытым исходным кодом), которые оборачивают библиотеки работы с PDF (например, PDFium) и предоставляют методы 1С для конвертации страниц PDF в картинки.

Преимущества:

В этом случае код в модуле менеджера будет выглядеть примерно так:


Компонента = Новый("AddIn.PDFComponent.PDFWrapper");
КартинкаДвоичныеДанные = Компонента.ПолучитьСтраницуКакКартинку(ПутьКФайлуPDF, НомерСтраницы);
// Далее вставляем картинку в ТабличныйДокумент

Решение 4: Система взаимодействия (для сложных сценариев)

Если вам необходимо инициировать действие на клиенте именно по событию с сервера (а не когда пользователь сам нажал кнопку), можно использовать механизм Системы взаимодействия (начиная с платформы 8.3.10).

Сценарий работы:

  1. Сервер понимает, что нужно что-то сделать на клиенте.
  2. Сервер отправляет сообщение конкретному пользователю или в обсуждение через СистемаВзаимодействия.ОтправитьСообщение().
  3. На клиенте в глобальном модуле или форме, которая всегда открыта, работает обработчик ОбработкаВнешнегоСобытия или подключенный обработчик сообщений системы взаимодействия.
  4. Клиент "ловит" сигнал и выполняет ЗапуститьПриложение().

Это более сложный архитектурный подход, который требует развернутого сервера взаимодействия, но он позволяет серверу "общаться" с клиентом.

Чего делать НЕ стоит

В обсуждении упоминался вариант с "хаками", такими как ПодключитьОбработчикОжидания. Разберем, почему это плохая практика:

Итог

Если ваша задача — печать из документа по кнопке:

  1. Проверьте, используется ли БСП.
  2. Если да — используйте ТипКоманды = "ВызовКлиентскогоМетода" и переносите логику запуска приложения в клиентский общий модуль.
  3. Если нет БСП — перепишите кнопку на форме так, чтобы она вызывала клиентскую процедуру, которая сначала подготавливает картинки (конвертирует PDF) на клиенте, а затем передает их на сервер для формирования табличного документа, либо формирует его сразу на клиенте.

Если задача — фоновая обработка без участия пользователя, единственным верным решением будет установка необходимого программного обеспечения (конвертеров) непосредственно на сервер 1С.

← На главную