В процессе разработки на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с ситуацией, когда код, идеально работающий во внешней обработке на локальном компьютере, внезапно перестает выполнять свои функции при переносе в серверный модуль. Одной из самых коварных функций в этом плане является ЗапуститьПриложение. Разберем по шагам, почему это происходит, что такое "Сессия 0" и как заставить сервер выполнять внешние скрипты (например, на Python или Batch).
Рассмотрим типичную ситуацию. Программист создает текстовый файл, записывает в него некий скрипт или данные и пытается открыть его стандартным приложением ОС (например, Блокнотом), используя метод ЗапуститьПриложение. На клиентском компьютере это приведет к открытию окна Блокнота. Однако, если этот же код вызвать в контексте &НаСервере, визуально ничего не произойдет.
Проанализируем пример кода, который часто вызывает вопросы:
Процедура СохранитьВФайлНаДиске(Скрипт) Экспорт
ТекстовыйФайл = Новый ТекстовыйДокумент;
ТекстовыйФайл.УстановитьТекст(Скрипт);
Генератор = Новый ГенераторСлучайныхЧисел(ТекущаяУниверсальнаяДатаВМиллисекундах());
ИмяФайла = "C:\tmp\" + Генератор.СлучайноеЧисло(0, 99) + ".txt";
ТекстовыйФайл.Записать(ИмяФайла);
ЗапуститьПриложение(ИмяФайла);
КонецПроцедуры
На первый взгляд, все верно: файл создается, путь корректен. Но при запуске на сервере пользователь не увидит открытого окна. Выясним причину этого поведения.
Главная причина кроется в архитектуре современных операционных систем Windows. Служба сервера 1С (процесс rphost.exe) работает в так называемой Сессии 0. Начиная с Windows Server 2008, эта сессия полностью изолирована от графического интерфейса пользователей.
Когда мы вызываем ЗапуститьПриложение на сервере:
notepad.exe).Важный вывод: на сервере нельзя запускать интерактивные приложения, требующие взаимодействия с пользователем.
Проанализируем, от чьего имени выполняется код. В клиент-серверном варианте сервер 1С обычно запускается от имени специального пользователя — USR1CV8. У этого пользователя:
C:\ или в папку C:\tmp.python.exe просто по имени, сервер может его не найти, так как путь к интерпретатору не прописан в системных переменных.Если ваша задача — не открыть Блокнот для чтения человеком, а выполнить фоновый скрипт (например, на Python), необходимо следовать определенным правилам. Рассмотрим наиболее надежный способ реализации через объект WScript.Shell, который предоставляет больше контроля, чем стандартный метод 1С.
Посмотрим на пример правильного вызова внешнего скрипта:
// Используем COM-объект для более тонкой настройки
Шелл = Новый COMОбъект("WScript.Shell");
// Обязательно используем полные пути к исполняемым файлам
ПутьКИнтерпретатору = """C:\Python\python.exe""";
ПутьКСкрипту = """C:\tmp\myscript.py""";
// Формируем команду. Кавычки важны, если в путях есть пробелы!
Команда = ПутьКИнтерпретатору + " " + ПутьКСкрипту;
// Запускаем.
// Параметр 0 означает "скрытое окно"
// Параметр Истина означает "дождаться завершения"
КодВозврата = Шелл.Run(Команда, 0, Истина);
Если КодВозврата <> 0 Тогда
ЗаписьЖурналаРегистрации("Ошибка запуска скрипта", УровеньЖурналаРегистрации.Ошибка,,, "Код ошибки: " + КодВозврата);
КонецЕсли;
ЗапуститьПриложение это второй параметр. Если его не установить в Истина, 1С продолжит выполнение кода, не дожидаясь, пока скрипт отработает. Если скрипт упадет с ошибкой через секунду, вы об этом не узнаете..exe файлам.python.exe script.py > log.txt 2>&1.USR1CV8 имеет права "Изменение" на папку, где лежит скрипт и куда он будет записывать результаты своей работы.Если вы все же предпочитаете использовать встроенный метод 1С, его синтаксис на сервере должен выглядеть так:
КодВозврата = 0;
Команда = """C:\Python\python.exe"" ""C:\scripts\process.py""";
ЗапуститьПриложение(Команда, , Истина, КодВозврата);
Если КодВозврата <> 0 Тогда
Сообщить("Скрипт завершился с ошибкой: " + КодВозврата);
КонецЕсли;
Резюме: Если вам нужно показать файл пользователю — делайте это на клиенте (&НаКлиенте). Если нужно обработать данные в фоновом режиме — используйте серверный вызов, полные пути и обязательно проверяйте права доступа системной учетной записи, под которой запущен сервер 1С.