Как запустить приложение от имени другого пользователя (администратора) в 1С?

Программист IT и автоматизация бизнеса
← На главную

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

Типичный пример такой задачи — необходимость отправить срочное оповещение пользователям терминального сервера (RDP) с помощью системной утилиты msg.exe. Если запустить команду msg * /server:ИмяСервера "Текст сообщения" через стандартный метод 1С ЗапуститьПриложение() из-под обычной учетной записи, операционная система вернет ошибку «Отказано в доступе». В рамках этой статьи мы подробно разберем, почему стандартные подходы не всегда работают, и рассмотрим пять эффективных практических способов решения данной проблемы.

Почему стандартные системные механизмы не подходят?

Проанализируем базовые варианты, которые первыми приходят на ум системным администраторам и разработчикам, и выясним их ключевые недостатки:

  1. Использование утилиты runas: Стандартная команда Windows runas /user:Administrator program.exe имеет критическое ограничение — она не умеет принимать пароль в качестве параметра командной строки из соображений безопасности. Система в любом случае потребует интерактивного ввода пароля в консоли. Использование ключа /savecred (сохранение учетных данных) работает локально и небезопасно в многопользовательской среде терминального сервера, так как любой пользователь сможет запустить любой процесс от имени сохраненного администратора.
  2. Запуск службы сервера 1С от имени Администратора: Это решение крайне небезопасно. Предоставление службе USR1CV8 прав локального или доменного администратора создает огромную брешь в безопасности всей корпоративной сети. В случае уязвимости в коде или выполнения произвольного кода через внешние обработки злоумышленник получит полный контроль над сервером.
  3. Использование WinAPI (CreateProcessAsUser): Этот метод требует написания сложного программного кода (чаще всего на C++ или C# в виде внешней компоненты), а также детального изучения механизмов управления токенами доступа Windows (Windows Access Tokens). Это избыточно сложно для решения утилитарных задач автоматизации.

Ниже мы подробно разберем по шагам изящные, безопасные и проверенные на практике альтернативные методы запуска приложений с повышенными правами.

---

Способ 1. Делегирование прав на отправку сообщений в RDP (Самое элегантное решение)

Выясним истинную причину проблемы. Почему утилита msg.exe выдает ошибку «Отказано в доступе» при вызове из-под системной учетной записи службы 1С? Дело вовсе не в отсутствии у пользователя прав локального администратора компьютера, а в отсутствии конкретного разрешения на отправку сообщений в настройках RDP-подключения (системный объект RDP-Tcp).

Windows позволяет точечно делегировать права на отправку системных сообщений обычным пользователям или группам без включения их в группу администраторов. Рассмотрим, как это настроить.

Администратору сервера достаточно один раз выполнить команду в консоли PowerShell от имени администратора:


wmic /namespace:\\root\CIMV2\TerminalServices PATH WIN32_TSAccount.TerminalName="RDP-TCP" call ModifyPermissions "BUILTIN\Remote Desktop Users", 7

Разберем параметры этой команды:

После выполнения этой настройки на стороне операционной системы, вам больше не понадобятся ухищрения с паролями в коде 1С. Вызов команды в коде будет выглядеть стандартно и безопасно:


ПараметрыЗапуска = "* /server:LOCAL_SERVER ""Уважаемые пользователи, сервер перезагрузится через 10 минут!""";
ЗапуститьПриложение("msg.exe " + ПараметрыЗапуска);

---

Способ 2. Использование Планировщика задач Windows как безопасного моста

Если особенности инфраструктуры не позволяют изменять права доступа RDP, мы можем использовать встроенный Планировщик задач Windows (Task Scheduler) в качестве безопасного посредника. Этот подход полностью исключает необходимость хранения пароля администратора в кодовой базе 1С.

Рассмотрим алгоритм настройки этого механизма по шагам:

Шаг 1. Создание задачи в Планировщике Windows:

  1. Откройте Планировщик задач (taskschd.msc) на сервере.
  2. Создайте новую простую задачу с именем, например, RunMsgSender.
  3. В свойствах задачи укажите, что она должна выполняться от имени учетной записи Администратора (или пользователя с правами администратора).
  4. Обязательно установите флаг «Выполнять с наивысшими правами» (Run with highest privileges).
  5. В качестве действия (Action) укажите запуск командного файла, например, C:\1C_Scripts\send_msg.bat.

Содержимое бат-файла send_msg.bat должно считывать параметры (текст сообщения) из заранее определенного временного текстового файла:


@echo off
set /p Message=<C:\1C_Scripts\temp_message.txt
msg * /server:localhost %Message%

Шаг 2. Вызов задачи из кода 1С:

В коде 1С перед запуском задачи мы сначала записываем текст сообщения во временный файл, а затем инициируем выполнение задачи планировщика через системную утилиту schtasks. Для запуска уже существующей задачи пользователю 1С не требуются административные права.


// Записываем текст сообщения во временный файл
Текст = Новый ЗаписьТекста("C:\1C_Scripts\temp_message.txt", КодировкаТекста.OEM);
Текст.ЗаписатьСтроку("Внимание! Технические работы.");
Текст.Закрыть();

// Запускаем задачу планировщика
ИмяЗадачи = "RunMsgSender";
КомандаЗапуска = "schtasks /run /tn """ + ИмяЗадачи + """";
ЗапуститьПриложение(КомандаЗапуска, , Истина); // Ждем завершения выполнения

Этот способ абсолютно безопасен, так как пароль администратора хранится в зашифрованном системном хранилище самого Планировщика задач, а не в коде конфигурации.

---

Способ 3. Использование инструментария WMI через COM-объект

Инструментарий управления Windows (WMI) предоставляет мощные возможности для удаленного и локального администрирования. С его помощью мы можем программно запустить любой процесс от имени другого пользователя. Для этого в 1С используется работа с COM-объектом WbemScripting.SWbemLocator.

Посмотрим на пример реализации данного метода:


Локатор = Новый COMОбъект("WbemScripting.SWbemLocator");

// Подключаемся к пространству имен WMI локального компьютера с явным указанием учетных данных администратора
Попытка
    СлужбаWMI = Локатор.ConnectServer(".", "root\cimv2", "ИмяАдминистратора", "ПарольАдминистратора");
    СлужбаWMI.Security_.ImpersonationLevel = 3; // Уровень имитации Impersonate
Исключение
    ЗаписьЖурналаРегистрации("ВнешнийЗапуск", УровеньЖурналаРегистрации.Ошибка, , , ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
    ВызватьИсключение "Не удалось подключиться к WMI под учетной записью администратора.";
КонецПопытки;

// Получаем доступ к классу Win32_Process для создания процессов
КлассПроцесс = СлужбаWMI.Get("Win32_Process");
ИдентификаторПроцесса = 0;
КомандаДляЗапуска = "msg * /server:localhost ""Сообщение отправлено через WMI!""";

// Метод Create запускает процесс в контексте безопасности указанного при подключении пользователя
Результат = КлассПроцесс.Create(КомандаДляЗапуска, Неопределено, Неопределено, ИдентификаторПроцесса);

Если Результат <> 0 Тогда
    ЗаписьЖурналаРегистрации("ВнешнийЗапуск", УровеньЖурналаРегистрации.Предупреждение, , , 
        "Ошибка создания процесса. Код возврата WMI: " + Строка(Результат));
Иначе
    ЗаписьЖурналаРегистрации("ВнешнийЗапуск", УровеньЖурналаРегистрации.Информация, , , 
        "Процесс успешно запущен. ID процесса: " + Строка(ИдентификаторПроцесса));
КонецЕсли;

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

---

Способ 4. Специализированные утилиты шифрования учетных данных (RunAsSpc / CPAU)

Если стороннее программное обеспечение разрешено к использованию на сервере, отличным решением станет применение специализированных утилит шифрования параметров запуска, таких как RunAsSpc или CPAU. Эти утилиты заменяют стандартный runas, позволяя передавать пароль в зашифрованном виде.

Проанализируем процесс работы с утилитой RunAsSpc:

  1. Администратор один раз запускает интерактивную утилиту генерации зашифрованных файлов (входит в комплект поставки программы).
  2. В интерфейсе утилиты указываются учетные данные администратора, путь к запускаемому файлу (например, к скрипту отправки сообщений) и параметры запуска.
  3. Утилита генерирует специальный зашифрованный файл-контейнер с расширением .spc (например, credential.spc). Пароль внутри этого файла надежно зашифрован ключом, привязанным к конкретному серверу.
  4. В коде 1С запуск утилиты выглядит максимально просто. Мы вызываем исполняемый файл утилиты и передаем ему путь к зашифрованному файлу конфигурации:

ИмяУтилиты = """C:\Program Files\RunAsSpc\runasspc.exe""";
ПутьКФайлуШифра = """C:\1C_Scripts\credential.spc""";
ПолнаяКоманда = ИмяУтилиты + " /cryptfile:" + ПутьКФайлуШифра;

ЗапуститьПриложение(ПолнаяКоманда, , Истина);

Этот способ объединяет в себе простоту вызова из кода 1С и высокий уровень безопасности хранения учетных данных администратора.

---

Способ 5. Использование VBScript (скрипт-обертка с эмуляцией ввода)

Разберем самый простой «обходной» вариант запуска без использования стороннего софта и изменения настроек WMI. Он заключается в динамическом создании временного скрипта на языке VBScript, который эмулирует ручной ввод пароля в консольное окно runas.

Этот способ отлично подходит для некритичных разовых задач, однако его не рекомендуется использовать для высоконагруженных систем, так как задержки выполнения (таймауты) зависят от текущей загрузки процессора сервера.

Посмотрим на пример формирования и запуска такого скрипта из кода 1С:


// Определяем пути к временным файлам
ИмяФайлаСкрипта = КаталогВременныхФайлов() + "runas_helper.vbs";

// Формируем текст скрипта VBScript
ЗаписьVBS = Новый ЗаписьТекста(ИмяФайлаСкрипта, КодировкаТекста.ANSI);
ЗаписьVBS.ЗаписатьСтроку("Set WshShell = CreateObject(""WScript.Shell"")");
// Запускаем runas
ЗаписьVBS.ЗаписатьСтроку("WshShell.Run ""runas /user:Administrator """"msg * /server:localhost Срочное сообщение для всех!""""""");
// Ожидаем 500 миллисекунд, пока откроется окно консоли для ввода пароля
ЗаписьVBS.ЗаписатьСтроку("WScript.Sleep 500");
// Отправляем символы пароля в активное окно
ЗаписьVBS.ЗаписатьСтроку("WshShell.SendKeys ""СуперПарольАдминистратора""");
// Нажимаем клавишу Enter
ЗаписьVBS.ЗаписатьСтроку("WshShell.SendKeys ""{ENTER}""");
ЗаписьVBS.Закрыть();

// Запускаем полученный скрипт
ЗапуститьПриложение("wscript.exe """ + ИмяФайлаСкрипта + """", , Истина);

// Удаляем временный файл после выполнения, чтобы не оставлять пароль на диске
Попытка
    УдалитьФайлы(ИмяФайлаСкрипта);
Исключение
    // Обработка возможных исключений удаления файла
КонецПопытки;

Внимание: Используйте данный метод с осторожностью. Если во время выполнения скрипта пользователь случайно переключит фокус на другое окно (например, на окно блокнота или браузера), метод SendKeys отправит символы пароля в это активное окно, что приведет к компрометации пароля.

---

Резюме и рекомендации

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

← На главную