如何在服务程序中启动桌面程序

做一Delphi程序,有一控件Tree允许接收拖放文件(使用TDropFileTarget),有帮助菜单打开CHM文件,发生奇怪现象。
现象:
1.控件Tree有时可以接收拖放,有时不可以。
2.CHM文件有时可以打开,有时打不开。
3.程序中有打开文件对话框,当转到桌面时,显示:C:\Documents   and   Settings\LocalService\桌面   引用了一个不可用的位置   ...
  有时就正常。

同时检查日志发现:
事件 ID ( 1903 )的描述(在资源( HHCTRL )中)无法找到。本地计算机可能没有必要的注册信息或消息 DLL 文件来从远端计算机显示消息。您可能可以使用 /AUXSOURCE= 标识来检索词描述;查看帮助和支持以了解详细信息。下列信息是事件的一部分: http://go.microsoft.com/fwlink?LinkID=45839.

百思不得其解,忽然注意到:LocalService不是任何登录用户,一般是Administrator。
恍然大悟,原来这个程序时发生的现象是因为: 程序正常是因为手动双击文件启动。而不正常,则是因为此程序使用服务(允许与桌面交互)启动。
测试,手动启动下,以上奇怪问题均消失。
以服务启动所需程序的方法:(服务默认以System帐户启动程序,故使用CreateProcessAsUser启动所需进程)
uses TLHelp32;

//取得Explorer.exe ProcessID
function GetExplorerProcessId:Hwnd;
var
  Pn: TProcesseNtry32;
  hProcess:THandle;
  H: Hwnd;
  Found: Boolean;
begin
  H := 0;
  Result := 0;

  //取所有进程的列表快照
  hProcess:= CreateToolHelp32SnapShot(TH32CS_SNAPALL, 0);
  Found := Process32First(sHandle, Pn);
  while Found do 
  begin
    if UpperCase(Pn.szExeFile) = 'EXPLORER.EXE' then
    begin
      Result := Pn.th32ProcessID;
      Exit;
    end;

    Found := Process32Next(sHandle, Pn);
  end;
end;

function StartProcessAsUser(const ACommandLine : String;AParam:String=''): Byte;
var
  hToken:thandle;
  ph:THandle;
  si:STARTUPINFO;
  pi:PROCESS_INFORMATION;
  ExplHwnd:Hwnd;
begin

  ExplHwnd:=GetExplorerProcessId;
  if ExplHwnd<=0 then Exit;

  ph:=OpenProcess(PROCESS_ALL_ACCESS ,
                 false,
                 ExplHwnd);    
  if ph<=0 then exit;

  OpenProcessToken( ph,TOKEN_ALL_ACCESS,hToken); //取Explorer进程Token===>取当前桌面帐户Token
  try
    ZeroMemory( @si, sizeof( STARTUPINFO ) );
    si.cb := sizeof( STARTUPINFO );
    Si.lpDesktop := PChar('Winsta0\Default');
    si.wShowWindow:=SW_SHOWNORMAL;
    CreateProcessAsUser(hToken,
                      pchar(ACommandLine) ,       
                      pchar(AParam),       
                      nil,
                      nil,
                      FALSE,
                      CREATE_DEFAULT_ERROR_MODE, 
                      nil,
                      nil,
                      si,
                      pi );
  finally
    closehandle(ph);
  end;
end;

转载于:https://www.cnblogs.com/saridon/archive/2008/07/06/1236986.html

你可能感兴趣的:(如何在服务程序中启动桌面程序)