Переход с файлового варианта работы информационной базы на клиент-серверный — это важный этап масштабирования системы. Однако именно на этом этапе программисты часто сталкиваются с ситуацией, когда привычный код перестает работать. Одной из самых распространенных проблем является "внезапный" отказ метода ЗапуститьПриложение(). Рассмотрим подробно, почему это происходит и как правильно организовать открытие файлов и запуск внешних программ в новой архитектуре.
Разберем ситуацию, описанную в теме. В файловом варианте всё работало корректно, потому что и база данных, и исполняемый код, и интерфейс пользователя находились в одном процессе на одном компьютере. При переходе на клиент-сервер ситуация радикально меняется. Проанализируем типичный ошибочный код, который часто встречается в модулях формы:
&НаСервере
Процедура ПереглядТаблНаСервере()
// Установка пути к файлу на диске D
ПользовательФайл = Строка(ПараметрыСеанса.ТекущийПользователь);
ИмяВремФайла = "d:\Temp\" + ПользовательФайл + ".pdf";
// Запись данных из базы на диск
СканДок.Записать(ИмяВремФайла);
// Попытка запустить приложение
ЗапуститьПриложение(ИмяВремФайла);
КонецПроцедуры
Выясним причину отказа: когда процедура помечена директивой &НаСервере, весь код внутри неё выполняется на стороне сервера 1С:Предприятия. Это влечет за собой две критические проблемы:
usr1cv8). Службы в Windows работают в изолированной "Сессии 0", которая не имеет графического интерфейса. Даже если команда ЗапуститьПриложение() сработает, программа (например, Adobe Reader или Excel) запустится в невидимом режиме на сервере под учетной записью службы. Пользователь на своем рабочем месте ничего не увидит.d:\Temp\ в серверном коде — это путь на жестком диске сервера. Если на сервере нет такого диска или у службы 1С нет прав на запись в эту папку, код прервется с ошибкой еще на этапе записи файла.Для того чтобы приложение открылось на компьютере пользователя, запуск должен инициироваться исключительно в контексте &НаКлиенте. Рассмотрим по шагам, как правильно реализовать эту задачу в клиент-серверной архитектуре.
Проанализируем правильную последовательность действий:
ЗапуститьПриложение() на клиенте.Рассмотрим пример кода, который будет надежно работать в любом режиме:
&НаСервере
Функция ПодготовитьФайлНаСервере()
// Получаем объект или данные из реквизита (например, СправочникСсылка или ДвоичныеДанные)
ДвоичныеДанныеФайла = СканДок.Получить();
// Помещаем во временное хранилище, чтобы клиент мог забрать файл
Возврат ПоместитьВоВременноеХранилище(ДвоичныеДанныеФайла, ЭтаФорма.УникальныйИдентификатор);
КонецФункции
&НаКлиенте
Процедура ОткрытьФайл(Команда)
// Шаг 1: Получаем адрес данных на сервере
АдресХранилища = ПодготовитьФайлНаСервере();
// Шаг 2: Определяем имя файла в локальном временном каталоге пользователя
ИмяФайла = КаталогВременныхФайлов() + "скан_документа.pdf";
// Шаг 3: Получаем данные из хранилища на клиент и записываем их на локальный диск
Данные = ПолучитьИзВременногоХранилища(АдресХранилища);
Данные.Записать(ИмяФайла);
// Шаг 4: Запускаем приложение на клиенте
ЗапуститьПриложение(ИмяФайла);
КонецПроцедуры
В данном примере мы используем функцию КаталогВременныхФайлов(), которая на клиенте всегда возвращает путь, к которому у текущего пользователя Windows точно есть права на запись. Это избавляет нас от проблем с правами доступа к папкам типа C:\Temp или D:\Temp.
Современные стандарты разработки 1С (начиная с версии платформы 8.3.15 и выше) настоятельно рекомендуют отказываться от синхронных методов в пользу асинхронных. Это особенно критично для работы в Веб-клиенте, где браузеры блокируют синхронные вызовы. Посмотрим на современный вариант решения задачи:
&НаКлиенте
Асинх Процедура ОткрытьФайлСовременно(Команда)
АдресХранилища = ПодготовитьФайлНаСервере();
ИмяФайла = КаталогВременныхФайлов() + "документ.pdf";
Данные = ПолучитьИзВременногоХранилища(АдресХранилища);
Ждать Данные.ЗаписатьАсинх(ИмяФайла);
// Используем асинхронный запуск
Ждать ЗапуститьПриложениеАсинх(ИмяФайла);
КонецПроцедуры
Применение ЗапуститьПриложениеАсинх() позволяет интерфейсу программы оставаться отзывчивым, пока операционная система обрабатывает запрос на открытие внешнего приложения.
Проанализируем еще несколько моментов, которые могут помешать запуску, даже если контекст выбран верно:
ЗапуститьПриложение(ИмяФайла) сработает только в том случае, если в операционной системе пользователя настроена ассоциация для данного расширения (например, .pdf связан с браузером или Acrobat Reader)./tmp/), а команда ЗапуститьПриложение может потребовать специфических настроек оболочки (shell).Подведем итог: Основная ошибка автора темы заключалась в попытке выполнить интерактивное действие (открытие окна) там, где окон не существует — на сервере. Разделяя логику подготовки данных (на сервере) и логику взаимодействия с пользователем (на клиенте), вы создаете надежное и масштабируемое решение, которое будет одинаково успешно работать и в файловом, и в клиент-серверном вариантах 1С.