Вопрос, поднятый пользователем, связан с необходимостью запуска консольного приложения от имени другого пользователя Windows через службу. Для этого используется функция CreateProcessWithLogonW, которая позволяет выполнить процесс с учетными данными другого пользователя. Однако, при попытке использовать данную функцию из службы, возникают проблемы.
Проблема
Автор вопроса разработал функцию RunAppAsAnotherWindowsUser, обертку над CreateProcessWithLogonW, которая должна позволять запускать консольные приложения от имени другого пользователя. Эта функция успешно работает в обычном Win32 VCL приложении, но не функционирует, когда вызывается из службы Windows.
Анализ проблемы
Службы Windows работают в изолированной сессии, которая не поддерживает интерактивные процессы. С Windows Vista и выше, сессия 0 предназначена исключительно для служб и не поддерживает процессы, взаимодействующие с пользователем. Службы запускаются в сессии 0, в то время как интерактивные сессии начинаются с сессии 1 и выше.
Подтвержденный ответ
Для запуска интерактивных процессов из службы необходимо получить токен пользователя, который находится в интерактивной сессии, и использовать его для создания нового процесса. Это можно сделать с помощью функций LogonUser и CreateProcessAsUser, где можно указать токен пользователя и сессию, в которой должен быть запущен процесс.
Альтернативный ответ
В случае, если необходимо использовать CreateProcessWithLogonW, можно получить токен пользователя с помощью функции LogonUser, изменить сессию с помощью SetTokenInformation, а затем использовать полученный токен для создания процесса с помощью CreateProcessAsUser. Однако, важно отметить, что в сессии службы (сессия 0) невозможно запустить интерактивные процессы, поэтому такая операция будет успешной только если есть интерактивный пользователь в системе.
Пример кода
uses
Advapi32, Wtsapi32;
var
hToken: THandle;
si: TStartupInfoW;
pi: TProcessInformation;
dwSession: DWORD;
begin
// Получение токена интерактивной сессии
if WTSQueryUserToken(WtsGetActiveConsoleSessionID, hToken) then
begin
// Изменение сессии токена
dwSession := WtsGetActiveConsoleSessionID;
SetTokenInformation(hToken, TokenSessionId, @dwSession, SizeOf(DWORD));
// Заполнение структуры TStartupInfoW
ZeroMemory(@si, SizeOf(TStartupInfoW));
si.cbSize := SizeOf(TStartupInfoW);
si.dwFlags := STARTF_USESHOWWINDOW;
si.wShowWindow := SW_HIDE; // Скрыть окно процесса
// Создание процесса с использованием токена пользователя
if CreateProcessAsUser(hToken, nil, 'cmd.exe', nil, nil, False,
CREATE_NO_WINDOW, nil, nil, si, pi) then
begin
// Ожидание завершения процесса
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
end;
end;
end;
Заключение
Для запуска консольного приложения от имени другого пользователя через службу Windows, необходимо использовать механизмы, позволяющие работать с интерактивными сессиями, такими как LogonUser, SetTokenInformation и CreateProcessAsUser. Важно понимать ограничения сессии службы и использовать соответствующие методы для работы с интерактивными процессами.
Контекст вопроса заключается в том, что необходимо запустить консольное приложение от имени другого пользователя на компьютере с операционной системой Windows, используя возможности запуска службы, но в силу ограничений безопасности и работы служб в отде
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.