При работе в конфигурациях на обычных формах, таких как 1С:Управление производственным предприятием (УПП), разработчики часто сталкиваются с проблемой разделения контекстов. В отличие от управляемых форм, где разделение на клиент и сервер выражено явно через директивы компиляции, в обычных формах внешняя обработка «видит» только файловую систему пользователя. Если возникает задача передать файл в защищенную папку на сервере и выполнить там консольный скрипт (например, на Node.js), требуется особый подход. В этой статье мы подробно разберем, как реализовать этот процесс, обойти ограничения прав доступа и гарантировать выполнение внешнего кода.
Первое, что нам необходимо осознать: код, исполняемый в модуле обычной формы, работает на стороне клиента. Файловая система сервера (например, диск C: на серверной машине) для него недоступна, если только это не сетевой ресурс. Для решения нашей задачи мы воспользуемся механизмом передачи данных через временное хранилище и создадим связующее звено в виде общего модуля.
Проанализируем общую схему действий:
ДвоичныеДанные.Чтобы код 1С мог работать с файлами непосредственно на сервере, нам нужно создать (или использовать существующий) общий модуль. В свойствах модуля обязательно должны быть установлены флажки Сервер и Вызов сервера. Это позволит нам обращаться к процедурам этого модуля из кода обработки, запущенной у пользователя.
Назовем наш модуль ФайловыйОбменСервер. Рассмотрим пример серверной процедуры, которая будет принимать адрес во временном хранилище и сохранять файл на диск:
Процедура СохранитьИВыполнитьНаСервере(АдресХранилища, ИмяФайла) Экспорт
// Получаем двоичные данные из временного хранилища
ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресХранилища);
// Определяем пути
КаталогПриемник = "D:\WorkFiles\source\"; // Используем путь вне Program Files для избежания проблем с правами
ПолныйПуть = КаталогПриемник + ИмяФайла;
Попытка
// Записываем файл на диск сервера
ДвоичныеДанные.Записать(ПолныйПуть);
// Запускаем обработку
ВыполнитьВнешнийСкрипт(ПолныйПуть);
Исключение
ЗаписьЖурналаРегистрации("Ошибка передачи файла", УровеньЖурналаРегистрации.Ошибка, , , ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
ВызватьИсключение "Не удалось сохранить файл на сервере. Проверьте права доступа.";
КонецПопытки;
КонецПроцедуры
В нашей обработке на обычной форме мы должны предоставить пользователю выбор файла и организовать его отправку. Разберем код, который будет вызываться при нажатии кнопки «Выполнить»:
Процедура КнопкаВыполнитьНажатие(Кнопка)
// Выбор файла пользователем
Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
Диалог.Фильтр = "PDF файлы (*.pdf)|*.pdf";
Если Диалог.Выбрать() Тогда
ВыбранныйПуть = Диалог.ПолноеИмяФайла;
ИмяФайла = Диалог.Имя;
// Преобразуем файл в двоичные данные на клиенте
ДанныеФайла = Новый ДвоичныеДанные(ВыбранныйПуть);
// Помещаем во временное хранилище
// Используем уникальный идентификатор формы, чтобы данные не удалились раньше времени
Адрес = ПоместитьВоВременноеХранилище(ДанныеФайла, ЭтаФорма.УникальныйИдентификатор);
// Вызываем серверную функцию из нашего общего модуля
ФайловыйОбменСервер.СохранитьИВыполнитьНаСервере(Адрес, ИмяФайла);
Сообщить("Файл успешно передан и отправлен на обработку.");
КонецЕсли;
КонецПроцедуры
Одной из ключевых сложностей является запуск index.js. На сервере 1С операционная система может не знать, чем открывать .js файлы, или открыть их в текстовом редакторе. Правильнее всего вызывать интерпретатор Node.js напрямую. Выясним, как это сделать правильно с помощью метода ЗапуститьПриложение.
Рассмотрим процедуру запуска подробнее:
Процедура ВыполнитьВнешнийСкрипт(ПутьКФайлу)
// Путь к исполняемому файлу Node.js и самому скрипту
// Важно: используем тройные кавычки для путей с пробелами
ПутьКNode = """C:\Program Files\nodejs\node.exe""";
ПутьКСкрипту = """C:\Program Files\src\index.js""";
Параметры = "--input " + """ + ПутьКФайлу + """;
СтрокаЗапуска = ПутьКNode + " " + ПутьКСкрипту + " " + Параметры;
// Используем второй параметр "Истина", чтобы 1С дождалась завершения скрипта
// Это критически важно, если мы хотим сразу прочитать результат обработки
КодВозврата = 0;
ЗапуститьПриложение(СтрокаЗапуска, , Истина, КодВозврата);
Если КодВозврата <> 0 Тогда
Сообщить("Скрипт завершился с ошибкой. Код: " + КодВозврата);
КонецЕсли;
КонецПроцедуры
Обратите внимание на использование параметра ДождатьсяЗавершения. Без него 1С продолжит выполнение кода, не дожидаясь, пока Node.js создаст выходной файл, что приведет к ошибке «Файл не найден» при попытке прочитать результат.
Если при выполнении ДвоичныеДанные.Записать() возникает ошибка доступа, проанализируем причины. В 90% случаев это связано с защитными механизмами Windows в папке C:\Program Files.
Почему это происходит:
USR1CV8). У этого пользователя по умолчанию нет прав на запись в системные каталоги.Program Files даже для администраторов, если приложение не запущено с повышенными привилегиями.Решение:
D:\Processing\).Program Files, убедимся, что у службы 1С есть право на «Чтение и выполнение» в этой директории, но для временных данных всё равно используем другой путь.Если стандартный метод ЗапуститьПриложение не обеспечивает нужной гибкости (например, если нужно скрыть консольное окно), мы можем использовать WScript.Shell. Рассмотрим этот пример:
Процедура ЗапускЧерезShell(Команда)
Shell = Новый COMОбъект("WScript.Shell");
// 0 - скрыть окно, Истина - ждать завершения
Shell.Run(Команда, 0, Истина);
КонецПроцедуры
Этот метод позволяет запустить скрипт полностью в фоновом режиме, что улучшает пользовательский опыт, так как на сервере не будут «мелькать» окна командной строки.
Мы проанализировали процесс передачи файлов на сервер в условиях использования обычных форм. Ключевым моментом здесь является правильное использование временного хранилища и общих модулей с серверным контекстом. Помните о специфике прав доступа в современных операционных системах: старайтесь выносить рабочие файлы за пределы системных папок и всегда проверяйте права учетной записи, под которой функционирует сервер 1С. Использование параметра ожидания в ЗапуститьПриложение и контроль кодов возврата сделают вашу интеграцию со сторонними скриптами надежной и стабильной.