Когда вы работаете с платформой 1С:Предприятие, особенно при разработке функционала, требующего взаимодействия с внешними системами или запуска приложений, вы можете столкнуться с необходимостью выполнить эти действия на сервере. Однако, если вы попытаетесь использовать стандартную процедуру ЗапуститьПриложение() в серверном коде, особенно в регламентных заданиях, то столкнетесь с ошибками или отсутствием реакции. В этой статье мы подробно разберем, почему так происходит, и предложим эффективное решение с использованием HTTP-запросов для сигнализирования внешним веб-сервисам, а также рассмотрим другие альтернативы для выполнения команд на сервере.
ЗапуститьПриложение() на сервере 1СДавайте выясним, почему процедура ЗапуститьПриложение(), которая отлично работает в клиентском коде, становится бесполезной на сервере.
ЗапуститьПриложение() изначально разработана для запуска внешних программ или открытия файлов в контексте клиентского приложения 1С. Это означает, что она ожидает наличия интерактивного пользовательского сеанса и доступа к рабочему столу, чтобы, например, открыть браузер, текстовый редактор или выполнить командный файл.ЗапуститьПриложение() из серверного кода, система не может найти среду для выполнения запрошенного действия, что приводит к ошибке или игнорированию команды.ЗапуститьПриложение() не работает.Очевидно, что ЗапуститьПриложение() не подходит для нашей задачи сигнализации сайту из регламентного задания. Нам нужно найти способ взаимодействия с внешними системами, который предназначен для серверного выполнения.
Как было справедливо отмечено в обсуждении, HTTP-запросы являются наиболее предпочтительным и надежным способом для взаимодействия с внешними веб-сервисами и сайтами из серверного кода 1С, включая регламентные задания. Этот метод стандартизирован, безопасен (особенно с использованием HTTPS) и полностью поддерживается платформой 1С для выполнения в фоновом режиме.
Для реализации HTTP-запросов в 1С мы будем использовать три ключевых объекта:
HTTPСоединение: Этот объект отвечает за установление связи с удаленным сервером. В его конструкторе мы указываем адрес сервера (хост), порт, данные для аутентификации (если требуются), параметры прокси-сервера и, что очень важно для HTTPS, объект защищенного соединения.HTTPЗапрос: С помощью этого объекта мы формируем сам запрос. Здесь мы определяем путь к ресурсу на сервере, метод запроса (например, GET, POST), добавляем необходимые заголовки (например, для авторизации или указания типа содержимого) и тело запроса (для POST-запросов).HTTPОтвет: Это результат выполнения нашего запроса. Из объекта HTTPОтвет мы можем получить код состояния HTTP (например, 200 для успеха, 404 для не найдено, 500 для ошибки сервера), заголовки ответа и тело ответа, которое может содержать данные в текстовом или двоичном формате.Большинство современных веб-сайтов используют защищенный протокол HTTPS для обеспечения конфиденциальности и целостности данных. Для работы с HTTPS в 1С нам потребуется объект ЗащищенноеСоединениеOpenSSL. Рассмотрим, как правильно создать объект HTTPСоединение для HTTPS.
Предположим, наш сайт — МойСайт.com, и нам нужно отправить запрос по HTTPS. Код будет выглядеть следующим образом:
HTTP = Новый HTTPСоединение(
"МойСайт.com", // сервер (хост)
443, // порт, по умолчанию для HTTP используется 80, для HTTPS 443
, // пользователь для доступа к серверу (если он есть, для базовой аутентификации)
, // пароль для доступа к серверу (если он есть)
, // здесь указывается прокси, если он есть (объект ИнтернетПрокси)
0, // таймаут в секундах, 0 или пусто - не устанавливать
Новый ЗащищенноеСоединениеOpenSSL() // объект защищенного соединения для HTTPS
);
Разберем параметры подробнее:
ИнтернетПрокси, настроенный соответствующим образом.Новый ЗащищенноеСоединениеOpenSSL(): Этот объект необходим для шифрования и дешифрования данных по протоколу SSL/TLS. Без него HTTPS-соединение не будет установлено. В простейшем случае его можно создать без параметров. Если требуется более сложная работа с сертификатами (например, проверка клиентских сертификатов), этот объект может принимать дополнительные параметры.Важный момент: Если ваш сайт использует HTTP вместо HTTPS, то порт будет 80, и параметр ЗащищенноеСоединениеOpenSSL() не нужен. Однако для безопасности всегда рекомендуется использовать HTTPS.
После установления соединения мы должны сформировать сам запрос, указав путь к ресурсу на сервере.
Предположим, нам нужно вызвать URL https://МойСайт.com/index.php?route=feed/import1c для сигнализации о загрузке файла. Объект HTTPЗапрос формируется следующим образом:
ПутьРесурса = "/index.php?route=feed/import1c";
Запрос = Новый HTTPЗапрос(ПутьРесурса);
А если ссылка выглядит как https://МойСайт.com/some/path/to/signal, без `.php` на конце?
Абсолютно никаких проблем! Веб-сервер сам знает, как обрабатывать такие URL (например, с помощью правил перенаправления или маршрутизации). Для объекта HTTPЗапрос важно только указать относительный путь от корня доменного имени. В этом случае, путь будет:
ПутьРесурса = "/some/path/to/signal";
Запрос = Новый HTTPЗапрос(ПутьРесурса);
Если вам нужно передать данные в запросе (например, параметры через POST-запрос или заголовки), вы можете использовать соответствующие методы объекта HTTPЗапрос, такие как УстановитьТелоИзСтроки(), УстановитьТелоИзДвоичныхДанных(), УстановитьЗаголовки().
Теперь, когда у нас есть настроенное соединение и сформированный запрос, мы можем отправить его и получить ответ.
Ответ = HTTP.Получить(Запрос);
Метод Получить() для HTTPСоединения используется для отправки GET-запроса. Если вам нужно отправить POST-запрос, вы используете метод Отправить(), передавая в него объект HTTPЗапрос, в котором уже настроено тело запроса.
После получения объекта Ответ нам необходимо проанализировать его, чтобы убедиться, что запрос был обработан успешно. Ключевым является свойство КодСостояния.
Мы также можем получить тело ответа (если сервер что-то возвращает) с помощью методов ПолучитьТелоКакСтроку() или ПолучитьТелоКакДвоичныеДанные().
Объединим все шаги в единый фрагмент кода, который можно использовать в серверной процедуре регламентного задания:
&НаСервере
Процедура СигнализироватьСайтуОЗагрузкеФайла()
// -----------------------------------------------------------
// Параметры для подключения к сайту
// -----------------------------------------------------------
СерверСайта = "МойСайт.com"; // Доменное имя вашего сайта
Порт = 443; // Порт для HTTPS. Для HTTP используйте 80
// Пользователь и пароль для базовой HTTP-аутентификации, если требуется
// ИмяПользователяСайта = "вашЛогин";
// ПарольСайта = "вашПароль";
// Относительный путь к ресурсу на сайте, который нужно вызвать
// Например, для URL https://МойСайт.com/index.php?route=feed/import1c -> "/index.php?route=feed/import1c"
// Для URL https://МойСайт.com/some/path/to/signal -> "/some/path/to/signal"
ПутьРесурса = "/index.php?route=feed/import1c"; // Пример пути
// Таймаут ожидания ответа от сервера в секундах. 0 - без таймаута.
// Рекомендуется устанавливать разумное значение.
Таймаут = 30;
// -----------------------------------------------------------
// Выполнение HTTP-запроса
// -----------------------------------------------------------
Попытка
// 1. Создаем объект защищенного соединения для HTTPS
ЗащищенноеСоединение = Новый ЗащищенноеСоединениеOpenSSL();
// 2. Устанавливаем HTTP-соединение с сайтом
// Если требуется базовая аутентификация, раскомментируйте параметры ИмяПользователяСайта и ПарольСайта
HTTP = Новый HTTPСоединение(
СерверСайта,
Порт,
, // ИмяПользователяСайта,
, // ПарольСайта,
, // Прокси-сервер (объект ИнтернетПрокси), если используется
Таймаут,
ЗащищенноеСоединение
);
// 3. Формируем HTTP-запрос
Запрос = Новый HTTPЗапрос(ПутьРесурса);
// Если нужны дополнительные заголовки (например, для POST-запроса или токена авторизации):
// Заголовки = Новый Соответствие;
// Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
// Заголовки.Вставить("Authorization", "Bearer ВашТокен");
// Запрос.УстановитьЗаголовки(Заголовки);
// Если это POST-запрос с телом (например, JSON-данные):
// ТелоЗапроса = "{\"ключ\":\"значение\"}";
// Запрос.УстановитьТелоИзСтроки(ТелоЗапроса, КодировкаТекста.UTF8);
// 4. Отправляем запрос и получаем ответ
// Для GET-запроса используем Получить(), для POST-запроса - Отправить(Запрос)
Ответ = HTTP.Получить(Запрос); // Для нашего случая сигнализации, скорее всего, это GET-запрос
// 5. Анализируем ответ от сервера
Если Ответ.КодСостояния = 200 Тогда
Сообщить("Успешная сигнализация сайту '" + СерверСайта + "'. Ответ сервера: " + Ответ.ПолучитьТелоКакСтроку());
// Здесь можно добавить логику обработки успешного ответа
Иначе
Сообщить("Ошибка при сигнализации сайту '" + СерверСайта + "'. Код состояния: " + Ответ.КодСостояния);
Сообщить("Детали ошибки: " + Ответ.ПолучитьТелоКакСтроку());
// Здесь можно добавить логику обработки ошибки, например, повтор запроса или логирование
КонецЕсли;
Исключение
Сообщить("Произошла критическая ошибка при выполнении HTTP-запроса: " + ОписаниеОшибки());
// Дополнительное логирование ошибок в журнал регистрации 1С
ЗаписьЖурналаРегистрации(
"HTTP-запрос",
УровеньЖурналаРегистрации.Ошибка,
, // ОбъектМетаданных
, // Данные
"Ошибка сигнализации сайту: " + ОписаниеОшибки()
);
КонецПопытки;
КонецПроцедуры
ЗапуститьПриложение() для выполнения серверных команд (не для веб-сигнализации)Хотя HTTP-запросы являются лучшим решением для взаимодействия с веб-сайтами, могут возникнуть ситуации, когда вам нужно выполнить какую-то команду непосредственно на сервере 1С (например, запустить локальную утилиту или скрипт). Для таких случаев есть другие подходы:
ФайловаяСистема.ЗапуститьПрограмму() (из БСП): Если ваша конфигурация использует Библиотеку стандартных подсистем (БСП), то в ней есть метод ЗапуститьПрограмму(). Этот метод позволяет более безопасно и контролируемо запускать внешние исполняемые файлы на сервере, а также получать код возврата и вывод программы (stdout, stderr). Это значительно предпочтительнее прямого использования WScript.Shell, так как он обычно имеет более продуманную обертку и обработку безопасности.WScript.Shell: В некоторых случаях можно использовать COM-объект WScript.Shell для выполнения команд на сервере. Однако этот метод имеет ряд ограничений и рисков:
Shell = Новый COMОбъект("WScript.Shell");
Результат = Shell.Run("cmd /c echo Hello World > C:\temp\log.txt", 0, Истина);
// 0 - стиль окна (скрытое), Истина - ждать завершения
WScript.Shell без глубокого понимания всех рисков и строжайшего контроля над исполняемыми командами.Для нашей изначальной задачи сигнализации сайту, HTTP-запросы остаются лучшим и самым безопасным решением.
При работе с HTTP-запросами и регламентными заданиями необходимо учитывать следующие моменты:
HTTPСоединения. Если внешний ресурс долго не отвечает, отсутствие таймаута может привести к зависанию регламентного задания и нехватке свободных рабочих процессов сервера 1С.ИнтернетПрокси и передать его в конструктор HTTPСоединения.КодировкаТекста.UTF8. Неправильная кодировка может привести к "кракозябрам" или некорректной обработке данных.Используя представленные подходы и примеры, вы сможете эффективно решить задачу взаимодействия 1С с внешними веб-сервисами из серверного кода, обходя ограничения ЗапуститьПриложение().