How can I call another application from my Delphi service?

前端 未结 3 1924
你的背包
你的背包 2020-12-19 11:53

I\'ve made a service with Delphi. Every time I call another application in that service the application is not running. What is wrong?

BTW I have used shellexecute,

相关标签:
3条回答
  • 2020-12-19 12:30

    ShellExecute/Ex() and CreateProcess() run the specified file/app in the same session as the calling process. A service always runs in session 0.

    In XP and earlier, the first user to log in also runs in session 0, so a service can run an interactive process and have it viewable to that interactive user, but only if the service is marked as interactive (the TService.Interactive property is true). If multiple users are logged in, they run in session 1+, and thus cannot see interactive processes run by services.

    Windows Vista introduced a new feature called "Session 0 Isolation". Interactive users no longer run in session 0 at all, they always run in session 1+ instead, and session 0 is not interactive at all (the TService.Interactive property no longer has any effect). However, to help with migration of legacy services, if a service runs an interactive process that tries to display a GUI on session 0, Windows prompts the current logged in user, if any, to switch to a separate desktop that temporarily makes the GUI viewable. In Windows 7 onwards, that legacy support is now gone.

    In all versions on Windows from 2000 onwards, the correct way to run an interactive process from a service and have it be viewable to an interactive user is to use CreateProcessAsUser() to run the new process in the specified user's session and desktop. There are plenty of detailed examples available on MSDN, StackOverflow, and throughout the Web, so I'm not going to reiterate them here.

    0 讨论(0)
  • 2020-12-19 12:41

    This solution is intended to be used from within a service, I thought I'd paste this code here as it was how I got my service to run an application as the currently logged in user.

    function WTSQueryUserToken(SessionId: ULONG; var phToken: THandle): BOOL; stdcall; external 'Wtsapi32.dll';
    
    procedure runApp(appName: String);
    var
      hToken: THandle;
      StartupInfo: TStartupInfo;
      ProcessInfo: TProcessInformation;
      res: boolean;
    
      begin
        GetStartupInfo(StartupInfo);
       if WTSQueryUserToken(WtsGetActiveConsoleSessionID, hToken) then
       begin
         res := CreateProcessAsUser(hToken, PWideChar(appName), nil, nil, nil, False, CREATE_NEW_CONSOLE, nil, nil, StartupInfo, ProcessInfo);
         if res then
          WaitForSingleObject(ProcessInfo.hProcess,INFINITE);
       end;
    end;
    

    //Anywhere in your service or app

    RunApp ('notepad.exe');
    
    0 讨论(0)
  • 2020-12-19 12:49

    Services run in a different session from the interactive user. Services run in session 0. Session 0 processes do not have access to the interactive desktop. Which means that any attempt to show an interactive process in session 0 is doomed to fail. You are attempting to create a Notepad process which is interactive.

    There are ways to launch a process on an interactive desktop from a session: Launching an interactive process from Windows Service in Windows Vista and later. As you will understand after reading that article, what you are attempting to do is non-trivial.

    0 讨论(0)
提交回复
热议问题