Разработка службы Windows с графическим интерфейсом в Delphi: использование CreateProcessAsUser для отображения окон в разных сессиях
Вопрос, поднятый пользователем, связан с созданием службы Windows в среде Delphi, которая должна запускать программу с графическим интерфейсом. При использовании функции WinExec программа запускается, но её окно не отображается на экране. Это происходит из-за того, что службы в Windows работают в сессии 0, где они изолированы от сессий пользователей. Для отображения окон в сессиях пользователей необходимо использовать функцию CreateProcessAsUser.
Подробнее о сессиях в Windows
В Windows существует несколько сессий, которые определяют, в каком контексте запускается процесс. В Windows XP и более старых версиях, первая сессия пользователя также работала в сессии 0. Однако начиная с Windows Vista, пользовательские сессии не совпадают с сессией 0, и службы больше не могут быть помечены как интерактивные. Это известно как "изоляция сессии 0". Для запуска процесса с графическим интерфейсом, который будет виден пользователю, служба должна использовать функцию CreateProcessAsUser, чтобы запустить процесс в интерактивной сессии.
Использование CreateProcessAsUser
Функция CreateProcessAsUser позволяет запустить процесс в контексте указанного пользователя, что важно для доступа к сессии пользователя из сессии службы. В отличие от WinExec и CreateProcess, которые запускают процесс в контексте вызывающего процесса, CreateProcessAsUser запускает процесс в указанном пользовательском аккаунте.
Пример кода на Object Pascal (Delphi)
uses
Advapi32;
var
TokenHandle: THandle;
StartupInfo: TStartupInfo;
ProcessInformation: TProcessInformation;
DomainName, UserName: string;
Password: PWCHAR;
LogonType, CreationFlags: DWORD;
TokenPrivileges: TTokenPrivilege;
Luid: TLUID;
TokenSource: TTokenSource;
begin
// Инициализация параметров для `LogonUser` и `CreateProcessAsUser`
DomainName := 'yourdomain';
UserName := 'username';
Password := PChar('password');
LogonType := LOGON32_LOGON_INTERACTIVE;
CreationFlags := CREATE_UNICODE_ENVIRONMENT;
Luid.LowPart := SE_TCB_NAME.value;
Luid.HighPart := 0;
TokenPrivileges.Level := TOKEN_PRIVILEGE_RESTRICTED;
TokenPrivileges.Attributes := SE_PRIVILEGE_ENABLED;
TokenPrivileges.Luid := Luid;
if not LogonUser(PChar(UserName), PChar(DomainName), Password, LogonType, LogonType, TokenHandle) then
RaiseLastOSError;
if not AdjustTokenPrivileges(TokenHandle, FALSE, @TokenPrivileges, SizeOf(TokenPrivileges), 0, 0) then
RaiseLastOSError;
ZeroMemory(@StartupInfo, SizeOf(TStartupInfo));
StartupInfo.cb := SizeOf(TStartupInfo);
StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
StartupInfo.wShowWindow := SW_SHOW;
if not CreateProcessAsUser(
TokenHandle,
nil,
PChar('c:\windows\system32\calc.exe'), // Пример запускакалькулятора
nil,
nil,
FALSE,
nil,
nil,
StartupInfo,
ProcessInformation) then
begin
RaiseLastOSError;
end;
// Ожидание завершения процесса, если необходимо
WaitForSingleObject(ProcessInformation.hProcess, INFINITE);
end;
Заключение
Использование CreateProcessAsUser позволяет службе Windows, созданной в Delphi, запускать программы с графическим интерфейсом, которые будут отображаться в сессиях пользователей, соблюдая при этом политику изоляции сессии 0. Важно правильно настроить параметры для LogonUser и CreateProcessAsUser, чтобы обеспечить корректный запуск процесса в нужной сессии.
Разработка службы Windows с графическим интерфейсом в Delphi, требующая использования функции `CreateProcessAsUser` для отображения окон в разных сессиях пользователя.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.