Почему не работает ЗапуститьПриложение() в клиент-серверной базе 1С и как это исправить?

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

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

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

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


&НаСервере
Процедура ПереглядТаблНаСервере()
    // Установка пути к файлу на диске D
    ПользовательФайл = Строка(ПараметрыСеанса.ТекущийПользователь);
    ИмяВремФайла = "d:\Temp\" + ПользовательФайл + ".pdf";
    
    // Запись данных из базы на диск
    СканДок.Записать(ИмяВремФайла); 
    
    // Попытка запустить приложение
    ЗапуститьПриложение(ИмяВремФайла);
КонецПроцедуры

Выясним причину отказа: когда процедура помечена директивой &НаСервере, весь код внутри неё выполняется на стороне сервера 1С:Предприятия. Это влечет за собой две критические проблемы:

  1. Изоляция сессий (Session 0 Isolation): Сервер 1С работает как системная служба (обычно под пользователем usr1cv8). Службы в Windows работают в изолированной "Сессии 0", которая не имеет графического интерфейса. Даже если команда ЗапуститьПриложение() сработает, программа (например, Adobe Reader или Excel) запустится в невидимом режиме на сервере под учетной записью службы. Пользователь на своем рабочем месте ничего не увидит.
  2. Различие файловых систем: Путь d:\Temp\ в серверном коде — это путь на жестком диске сервера. Если на сервере нет такого диска или у службы 1С нет прав на запись в эту папку, код прервется с ошибкой еще на этапе записи файла.

Правильный алгоритм: Перенос исполнения на клиент

Для того чтобы приложение открылось на компьютере пользователя, запуск должен инициироваться исключительно в контексте &НаКлиенте. Рассмотрим по шагам, как правильно реализовать эту задачу в клиент-серверной архитектуре.

Проанализируем правильную последовательность действий:

  1. На сервере получаем двоичные данные файла из базы данных.
  2. Передаем эти данные во временное хранилище.
  3. Возвращаем адрес хранилища на клиент.
  4. На клиенте получаем данные из хранилища и сохраняем их в локальный временный каталог пользователя.
  5. Вызываем ЗапуститьПриложение() на клиенте.

Пример реализации корректного кода

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


&НаСервере
Функция ПодготовитьФайлНаСервере()
    // Получаем объект или данные из реквизита (например, СправочникСсылка или ДвоичныеДанные)
    ДвоичныеДанныеФайла = СканДок.Получить(); 
    
    // Помещаем во временное хранилище, чтобы клиент мог забрать файл
    Возврат ПоместитьВоВременноеХранилище(ДвоичныеДанныеФайла, ЭтаФорма.УникальныйИдентификатор);
КонецФункции

&НаКлиенте
Процедура ОткрытьФайл(Команда)
    // Шаг 1: Получаем адрес данных на сервере
    АдресХранилища = ПодготовитьФайлНаСервере();
    
    // Шаг 2: Определяем имя файла в локальном временном каталоге пользователя
    ИмяФайла = КаталогВременныхФайлов() + "скан_документа.pdf";
    
    // Шаг 3: Получаем данные из хранилища на клиент и записываем их на локальный диск
    Данные = ПолучитьИзВременногоХранилища(АдресХранилища);
    Данные.Записать(ИмяФайла);
    
    // Шаг 4: Запускаем приложение на клиенте
    ЗапуститьПриложение(ИмяФайла);
КонецПроцедуры

В данном примере мы используем функцию КаталогВременныхФайлов(), которая на клиенте всегда возвращает путь, к которому у текущего пользователя Windows точно есть права на запись. Это избавляет нас от проблем с правами доступа к папкам типа C:\Temp или D:\Temp.

Использование асинхронных вызовов

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


&НаКлиенте
Асинх Процедура ОткрытьФайлСовременно(Команда)
    АдресХранилища = ПодготовитьФайлНаСервере();
    ИмяФайла = КаталогВременныхФайлов() + "документ.pdf";
    
    Данные = ПолучитьИзВременногоХранилища(АдресХранилища);
    Ждать Данные.ЗаписатьАсинх(ИмяФайла);
    
    // Используем асинхронный запуск
    Ждать ЗапуститьПриложениеАсинх(ИмяФайла);
КонецПроцедуры

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

Важные нюансы безопасности и прав доступа

Проанализируем еще несколько моментов, которые могут помешать запуску, даже если контекст выбран верно:

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

← На главную