나는 서비스를 작성하고 그것에서 애플리케이션 (GUI 포함)을 실행하고 싶습니다. 그래서 아래와 같은 절차를 작성합니다. 내 응용 프로그램이 시작되었지만 여전히 서비스 세션에 있습니다! 그래서 나는 그것이 GUI를 볼 수 없습니다.
도와주세요.
Procedure RunAppFromService(Path, FileName: string);
var
zPath : array[0..512] of char;
zAppName : array[0..512] of char;
StartupInfo : TStartupInfo;
ProcessInfo : TProcessInformation;
begin { WinExecAndWait32V2 }
StrPCopy(zPath, Path);
StrPCopy(zAppName, FileName);
FillChar(StartupInfo, Sizeof(StartupInfo), #0);
StartupInfo.cb := Sizeof(StartupInfo);
StartupInfo.lpDesktop := PChar('winsta0\Default');
StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
StartupInfo.wShowWindow := Visibility;
FillChar(ProcessInfo, Sizeof(ProcessInfo), #0);
CreateProcessAsUser(0, nil,
zAppName, { pointer to command line string }
nil, { pointer to process security attributes }
nil, { pointer to thread security attributes }
false, { handle inheritance flag }
CREATE_NEW_CONSOLE or { creation flags }
NORMAL_PRIORITY_CLASS,
nil, { pointer to new environment block }
zPath, { pointer to current directory name }
StartupInfo, { pointer to STARTUPINFO }
ProcessInfo); { pointer to PROCESS_INF }
end;
당신은 호출 할 필요가 WTSQueryUserToken을 함께 WtsGetActiveConsoleSessionID 다음에 전달할 토큰 현재 활성 사용자를 얻을 수 CreateEnvironmentBlock 및 CreateProcessAsUserW .
function WTSQueryUserToken(SessionId: ULONG; var phToken: THandle): BOOL; stdcall; external 'Wtsapi32.dll';
function CreateEnvironmentBlock(var lpEnvironment: Pointer;
hToken: THandle;
bInherit: BOOL): BOOL;
stdcall; external 'Userenv.dll';
function DestroyEnvironmentBlock(pEnvironment: Pointer): BOOL; stdcall; external 'Userenv.dll';
function RunAppFromService(const Path, FileName: string): Boolean;
var
zPath : array[0..512] of char;
zAppName : array[0..512] of char;
StartupInfo : TStartupInfo;
ProcessInfo : TProcessInformation;
hUserToken : THandle;
p : Pointer;
begin { WinExecAndWait32V2 }
Result := False;
StrPCopy(zPath, Path);
StrPCopy(zAppName, FileName);
if NOT WTSQueryUserToken(WtsGetActiveConsoleSessionID, hUserToken) then exit;
if CreateEnvironmentBlock(P, hUserToken, True) then
begin
ZeroMemory(@StartupInfo, sizeof(StartupInfo));
StartupInfo.lpDesktop := ('winsta0\default');
StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
StartupInfo.wShowWindow := Visibility;
if CreateProcessAsUserW(
hUserToken,
nil,
zAppName,
nil,
nil,
False,
CREATE_UNICODE_ENVIRONMENT,
P,
zPath,
StartupInfo,
ProcessInfo) then
begin
Result := True;
end;
CloseHandle(ProcessInfo.hProcess);
CloseHandle(ProcessInfo.hThread);
DestroyEnvironmentBlock(P);
end;
if hUserToken <> INVALID_HANDLE_VALUE then
CloseHandle(hUserToken);
end;
Remy의 의견 및 조언에 따라 업데이트
참고 : WTSQueryUserToken () 은 서비스가 SYSTEM 계정에서 실행중인 경우에만 작동합니다.
type
WTS_INFO_CLASS = (
WTSInitialProgram,
WTSApplicationName,
WTSWorkingDirectory,
WTSOEMId,
WTSSessionId,
WTSUserName,
WTSWinStationName,
WTSDomainName,
WTSConnectState,
WTSClientBuildNumber,
WTSClientName,
WTSClientDirectory,
WTSClientProductId,
WTSClientHardwareId,
WTSClientAddress,
WTSClientDisplay,
WTSClientProtocolType,
WTSIdleTime,
WTSLogonTime,
WTSIncomingBytes,
WTSOutgoingBytes,
WTSIncomingFrames,
WTSOutgoingFrames,
WTSClientInfo,
WTSSessionInfo,
WTSSessionInfoEx,
WTSConfigInfo,
WTSValidationInfo,
WTSSessionAddressV4,
WTSIsRemoteSession
);
WTS_CONNECTSTATE_CLASS = (
WTSActive,
WTSConnected,
WTSConnectQuery,
WTSShadow,
WTSDisconnected,
WTSIdle,
WTSListen,
WTSReset,
WTSDown,
WTSInit
);
PWTS_SESSION_INFO = ^WTS_SESSION_INFO;
WTS_SESSION_INFO = record
SessionId: DWORD;
pWinStationName: LPTSTR;
State: WTS_CONNECTSTATE_CLASS;
end;
........
function WTSEnumerateSessions(hServer: THandle; Reserved: DWORD; Version: DWORD; var ppSessionInfo: PWTS_SESSION_INFO; var pCount: DWORD): BOOL; stdcall; external 'Wtsapi32.dll' name {$IFDEF UNICODE}'WTSEnumerateSessionsW'{$ELSE}'WTSEnumerateSessionsA'{$ENDIF};
procedure WTSFreeMemory(pMemory: Pointer); stdcall; external 'Wtsapi32.dll';
function WTSQueryUserToken(SessionId: ULONG; var phToken: THandle): BOOL; stdcall; external 'Wtsapi32.dll';
function CreateEnvironmentBlock(var lpEnvironment: Pointer;
hToken: THandle;
bInherit: BOOL): BOOL;
stdcall; external 'Userenv.dll';
function DestroyEnvironmentBlock(pEnvironment: Pointer): BOOL; stdcall; external 'Userenv.dll';
function RunAppFromService(const Path, FileName: string): Boolean;
const
WTS_CURRENT_SERVER_HANDLE: THandle = 0;
var
zPath : array[0..512] of char;
zAppName : array[0..512] of char;
StartupInfo : TStartupInfo;
ProcessInfo : TProcessInformation;
hUserToken : THandle;
p : Pointer;
Sessions, Session : PWTS_SESSION_INFO;
NumSessions : DWORD;
I : Integer;
begin { WinExecAndWait32V2 }
Result := False;
StrPCopy(zPath, Path);
StrPCopy(zAppName, FileName);
if not WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, Sessions, NumSessions) then
exit;;
try
if NumSessions > 0 then
begin
Session := Sessions;
for I := 0 to NumSessions-1 do
begin
if Session.State = WTSActive then
begin
if WTSQueryUserToken(Session.SessionId, hUserToken) then begin
if CreateEnvironmentBlock(P, hUserToken, True) then
begin
ZeroMemory(@StartupInfo, sizeof(StartupInfo));
StartupInfo.lpDesktop := ('winsta0\default');
StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
StartupInfo.wShowWindow := Visibility;
if CreateProcessAsUserW(
hUserToken,
nil,
zAppName,
nil,
nil,
False,
CREATE_UNICODE_ENVIRONMENT,
P,
zPath,
StartupInfo,
ProcessInfo) then
begin
Result := True;
end;
CloseHandle(ProcessInfo.hProcess);
CloseHandle(ProcessInfo.hThread);
DestroyEnvironmentBlock(P);
end;
if hUserToken <> INVALID_HANDLE_VALUE then
CloseHandle(hUserToken);
end;
end;
Inc(Session);
end;
end;
finally
WTSFreeMemory(Sessions);
end;
end;
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다