Как передать файлы на сервер и запустить внешний скрипт в 1С:УПП на обычных формах

Программист 1С v8.3 (Обычные формы) Промышленность, строительство и АПК
← На главную

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

Понимание принципа взаимодействия клиента и сервера

Первое, что нам необходимо осознать: код, исполняемый в модуле обычной формы, работает на стороне клиента. Файловая система сервера (например, диск C: на серверной машине) для него недоступна, если только это не сетевой ресурс. Для решения нашей задачи мы воспользуемся механизмом передачи данных через временное хранилище и создадим связующее звено в виде общего модуля.

Проанализируем общую схему действий:

  1. Считывание файла на клиенте и его преобразование в ДвоичныеДанные.
  2. Помещение данных во временное хранилище для передачи на сервер.
  3. Вызов серверной процедуры из общего модуля, который имеет доступ к файловой системе сервера.
  4. Извлечение данных из хранилища и запись их на диск сервера.
  5. Запуск внешнего скрипта и ожидание результата.

Шаг 1: Подготовка общего модуля

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

Назовем наш модуль ФайловыйОбменСервер. Рассмотрим пример серверной процедуры, которая будет принимать адрес во временном хранилище и сохранять файл на диск:


Процедура СохранитьИВыполнитьНаСервере(АдресХранилища, ИмяФайла) Экспорт
    
    // Получаем двоичные данные из временного хранилища
    ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресХранилища);
    
    // Определяем пути
    КаталогПриемник = "D:\WorkFiles\source\"; // Используем путь вне Program Files для избежания проблем с правами
    ПолныйПуть = КаталогПриемник + ИмяФайла;
    
    Попытка
        // Записываем файл на диск сервера
        ДвоичныеДанные.Записать(ПолныйПуть);
        
        // Запускаем обработку
        ВыполнитьВнешнийСкрипт(ПолныйПуть);
    Исключение
        ЗаписьЖурналаРегистрации("Ошибка передачи файла", УровеньЖурналаРегистрации.Ошибка, , , ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
        ВызватьИсключение "Не удалось сохранить файл на сервере. Проверьте права доступа.";
    КонецПопытки;
    
КонецПроцедуры

Шаг 2: Реализация передачи файла с клиента

В нашей обработке на обычной форме мы должны предоставить пользователю выбор файла и организовать его отправку. Разберем код, который будет вызываться при нажатии кнопки «Выполнить»:


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

Шаг 3: Запуск внешнего скрипта и управление ожиданием

Одной из ключевых сложностей является запуск 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.

Почему это происходит:

Решение:

  1. Создадим отдельный рабочий каталог на диске (например, D:\Processing\).
  2. Дадим полные права пользователю, от имени которого работает служба «Агент сервера 1С:Предприятие», на эту папку.
  3. Если скрипты обязаны лежать в Program Files, убедимся, что у службы 1С есть право на «Чтение и выполнение» в этой директории, но для временных данных всё равно используем другой путь.

Использование COM-объектов для продвинутого запуска

Если стандартный метод ЗапуститьПриложение не обеспечивает нужной гибкости (например, если нужно скрыть консольное окно), мы можем использовать WScript.Shell. Рассмотрим этот пример:


Процедура ЗапускЧерезShell(Команда)
    
    Shell = Новый COMОбъект("WScript.Shell");
    // 0 - скрыть окно, Истина - ждать завершения
    Shell.Run(Команда, 0, Истина);
    
КонецПроцедуры

Этот метод позволяет запустить скрипт полностью в фоновом режиме, что улучшает пользовательский опыт, так как на сервере не будут «мелькать» окна командной строки.

Заключение

Мы проанализировали процесс передачи файлов на сервер в условиях использования обычных форм. Ключевым моментом здесь является правильное использование временного хранилища и общих модулей с серверным контекстом. Помните о специфике прав доступа в современных операционных системах: старайтесь выносить рабочие файлы за пределы системных папок и всегда проверяйте права учетной записи, под которой функционирует сервер 1С. Использование параметра ожидания в ЗапуститьПриложение и контроль кодов возврата сделают вашу интеграцию со сторонними скриптами надежной и стабильной.

← На главную