내 응용 프로그램이 서비스 세션으로 이동합니다 (콘솔 대신).

레자 사디 그

나는 서비스를 작성하고 그것에서 애플리케이션 (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 다음에 전달할 토큰 현재 활성 사용자를 얻을 수 CreateEnvironmentBlockCreateProcessAsUserW .

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] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

분류에서Dev

Windows 서비스에서 콘솔 응용 프로그램으로 반복적으로 데이터 전송

분류에서Dev

콘솔 응용 프로그램에서 신호음이 울리는 이유는 무엇입니까?

분류에서Dev

MATLAB 내에서 C # 콘솔 응용 프로그램 실행

분류에서Dev

C #에서 대규모 데이터베이스로 콘솔 응용 프로그램을 실행하는 동안 높은 메모리 소비

분류에서Dev

콘솔 응용 프로그램 및 ssh에서 마우스 이동

분류에서Dev

asp.net Core에서 콘솔 응용 프로그램과 웹 응용 프로그램의 차이점

분류에서Dev

콘솔 응용 프로그램에서 WCF 서비스 사용

분류에서Dev

콘솔 응용 프로그램에서 텍스트 블록의 높이 결정

분류에서Dev

C ++에서 내 콘솔 응용 프로그램으로 열린 파일 읽기

분류에서Dev

WindowsForm 응용 프로그램은 Visual Studio에서 콘솔 응용 프로그램을 생성합니다.

분류에서Dev

콘솔에 표시되는 내용을 수신자에게 보내는 Java 프로그램에서 이메일을 어떻게 보내나요?

분류에서Dev

마우스 클릭시 콘솔 응용 프로그램이 멈춤

분류에서Dev

C ++ 클라이언트 서버 콘솔 응용 프로그램 오류

분류에서Dev

C ++ 클라이언트 서버 콘솔 응용 프로그램 오류

분류에서Dev

C ++ 클라이언트 서버 콘솔 응용 프로그램 오류

분류에서Dev

Windows 8.1에서 C # 콘솔 응용 프로그램이 인쇄되지 않음

분류에서Dev

어떻게 콘솔에서 서버로 내 응용 프로그램을 시작?

분류에서Dev

SAP HANA DB 연결은 콘솔 응용 프로그램에서 제대로 작동하지만 서비스에서는 동일한 것이 작동하지 않습니다.

분류에서Dev

arraylist에 막대한 양의 비트 맵을로드하면 내 응용 프로그램이 충돌합니다.

분류에서Dev

응용 프로그램에서 Google지도에서 차례대로 내비게이션

분류에서Dev

C ++ Windows OS에서 파일 생성 날짜를 얻는 방법이 내 콘솔 응용 프로그램을 충돌시킵니다.

분류에서Dev

내 응용 프로그램에서 Windows 10 콘솔 "표시"모드 끄기

분류에서Dev

C #에서 콘솔 응용 프로그램을 자동으로 일시 중지

분류에서Dev

콘솔 응용 프로그램에서 ASP.NET WebAPI로 전달 된 데이터에서 DocumentDB에 문서를 만들 때 내부 서버 오류 (500)

분류에서Dev

다른 콘솔 응용 프로그램에서 WPF 응용 프로그램에서 작업 시작

분류에서Dev

명명 된 파이프에서 Oracle 콘솔 응용 프로그램의 출력 리디렉션

분류에서Dev

C # : .Net : 콘솔 응용 프로그램에서 작동하는 코드. WCF 서비스에서 실행할 때 동일한 코드가 실패합니다.

분류에서Dev

콘솔 응용 프로그램 대상 .NET 5를 만들 수 없습니다.

분류에서Dev

Windows 8 용 Visual Studio 2012에서 win32 콘솔 응용 프로그램 옵션이 표시되지 않음

Related 관련 기사

  1. 1

    Windows 서비스에서 콘솔 응용 프로그램으로 반복적으로 데이터 전송

  2. 2

    콘솔 응용 프로그램에서 신호음이 울리는 이유는 무엇입니까?

  3. 3

    MATLAB 내에서 C # 콘솔 응용 프로그램 실행

  4. 4

    C #에서 대규모 데이터베이스로 콘솔 응용 프로그램을 실행하는 동안 높은 메모리 소비

  5. 5

    콘솔 응용 프로그램 및 ssh에서 마우스 이동

  6. 6

    asp.net Core에서 콘솔 응용 프로그램과 웹 응용 프로그램의 차이점

  7. 7

    콘솔 응용 프로그램에서 WCF 서비스 사용

  8. 8

    콘솔 응용 프로그램에서 텍스트 블록의 높이 결정

  9. 9

    C ++에서 내 콘솔 응용 프로그램으로 열린 파일 읽기

  10. 10

    WindowsForm 응용 프로그램은 Visual Studio에서 콘솔 응용 프로그램을 생성합니다.

  11. 11

    콘솔에 표시되는 내용을 수신자에게 보내는 Java 프로그램에서 이메일을 어떻게 보내나요?

  12. 12

    마우스 클릭시 콘솔 응용 프로그램이 멈춤

  13. 13

    C ++ 클라이언트 서버 콘솔 응용 프로그램 오류

  14. 14

    C ++ 클라이언트 서버 콘솔 응용 프로그램 오류

  15. 15

    C ++ 클라이언트 서버 콘솔 응용 프로그램 오류

  16. 16

    Windows 8.1에서 C # 콘솔 응용 프로그램이 인쇄되지 않음

  17. 17

    어떻게 콘솔에서 서버로 내 응용 프로그램을 시작?

  18. 18

    SAP HANA DB 연결은 콘솔 응용 프로그램에서 제대로 작동하지만 서비스에서는 동일한 것이 작동하지 않습니다.

  19. 19

    arraylist에 막대한 양의 비트 맵을로드하면 내 응용 프로그램이 충돌합니다.

  20. 20

    응용 프로그램에서 Google지도에서 차례대로 내비게이션

  21. 21

    C ++ Windows OS에서 파일 생성 날짜를 얻는 방법이 내 콘솔 응용 프로그램을 충돌시킵니다.

  22. 22

    내 응용 프로그램에서 Windows 10 콘솔 "표시"모드 끄기

  23. 23

    C #에서 콘솔 응용 프로그램을 자동으로 일시 중지

  24. 24

    콘솔 응용 프로그램에서 ASP.NET WebAPI로 전달 된 데이터에서 DocumentDB에 문서를 만들 때 내부 서버 오류 (500)

  25. 25

    다른 콘솔 응용 프로그램에서 WPF 응용 프로그램에서 작업 시작

  26. 26

    명명 된 파이프에서 Oracle 콘솔 응용 프로그램의 출력 리디렉션

  27. 27

    C # : .Net : 콘솔 응용 프로그램에서 작동하는 코드. WCF 서비스에서 실행할 때 동일한 코드가 실패합니다.

  28. 28

    콘솔 응용 프로그램 대상 .NET 5를 만들 수 없습니다.

  29. 29

    Windows 8 용 Visual Studio 2012에서 win32 콘솔 응용 프로그램 옵션이 표시되지 않음

뜨겁다태그

보관