我建立了一个Service   Application,中间有一个Thread,在一定条件下,我需要它运行另一个外部的程序。  
  可以当我启动服务,外部程序并没有显示的运行,在任务管理器中可以看到,而且不能够终止。  
   
  请问这是为什么,要怎样才能够解决。  
   
  代码大概是这样子的:  
   
  unit   Unit1;  
   
  interface  
   
  uses  
      Windows,   Messages,   SysUtils,   Classes,   Graphics,   Controls,   SvcMgr,   Dialogs;  
   
  type  
      T   =   class(TThread)  
      protected  
          procedure   Execute;   override;  
   
      end;  
   
   
      TService1   =   class(TService)  
          procedure   ServiceStart(Sender:   TService;   var   Started:   Boolean);  
      private  
          {   Private   declarations   }  
          tt:   T;  
      public  
          function   GetServiceController:   TServiceController;   override;  
          {   Public   declarations   }  
      end;  
   
  var  
      Service1:   TService1;  
   
  implementation  
   
  {$R   *.DFM}  
   
  procedure   ServiceController(CtrlCode:   DWord);   stdcall;  
  begin  
      Service1.Controller(CtrlCode);  
  end;  
   
  function   TService1.GetServiceController:   TServiceController;  
  begin  
      Result   :=   ServiceController;  
  end;  
   
  procedure   T.Execute;  
  begin  
      while   true   do  
      begin  
          if   fileexists('c:\start.txt')   then   
              winexec('notepad.exe',   SW_SHOWNORMAL);   //运行一个程序,但看不到窗口,用ShellExecute也一样
  
          sleep(1000);  
      end;  
  end;  
                                                                                           
  procedure   TService1.ServiceStart(Sender:   TService;   var   Started:   Boolean);  
  begin  
      tt   :=   T.Create(false);  
      Started   :=   True;  
  end;  
   
  end. 

解决方案 »

  1.   

    你要指定是winsta0\\default才行
    否则系统会默认是服务桌面而不是系统桌面,运行的程序会在服务桌面显示出来,当前屏幕下自然看不到了
      

  2.   

    恩,具体要怎么解决,我找很久了,大多都说用CreateProcessAsUser,
    不过我不太了解
      

  3.   

      WTSQueryUserToken(dwSessionId, hUserToken);
      dwCreationFlags := NORMAL_PRIORITY_CLASS or CREATE_NEW_CONSOLE;
      ZeroMemory(@si, sizeof(STARTUPINFO));
      si.cb := sizeof(STARTUPINFO);
      si.lpDesktop := 'winsta0\default';
      ZeroMemory(@pi, sizeof(pi));
      hProcess := OpenProcess(MAXIMUM_ALLOWED, FALSE, winlogonPid);  if (not OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY
        or TOKEN_DUPLICATE or TOKEN_ASSIGN_PRIMARY or TOKEN_ADJUST_SESSIONID
        or TOKEN_READ or TOKEN_WRITE, hPToken)) then
      begin
        abcd := GetLastError();
        err('Process token open Error: ' + inttostr(GetLastError()));
      end;  if (not LookupPrivilegeValue(nil, SE_DEBUG_NAME, tp.Privileges[0].Luid)) then
      begin
        err('Lookup Privilege value Error: ' + inttostr(GetLastError()));
      end;
      tp.PrivilegeCount := 1;
      tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;  DuplicateTokenEx(hPToken, MAXIMUM_ALLOWED, nil,
        SecurityIdentification, TokenPrimary, hUserTokenDup);
      dup := GetLastError();  // Adjust Token privilege  SetTokenInformation(hUserTokenDup,
        TokenSessionId, pointer(dwSessionId), sizeof(DWORD));  if (not AdjustTokenPrivileges(hUserTokenDup, FALSE, @tp, sizeof(TOKEN_PRIVILEGES),
        nil, nil)) then
      begin
        abc := GetLastError();
        err('Adjust Privilege value Error: ' + inttostr(GetLastError()));
      end;  if (GetLastError() = ERROR_NOT_ALL_ASSIGNED) then
      begin
        err('Token does not have the provilege');
      end;  lpEnv := nil;  if (CreateEnvironmentBlock(lpEnv, hUserTokenDup, TRUE)) then
      begin
        dwCreationFlags := dwCreationFlags or CREATE_UNICODE_ENVIRONMENT;
      end
      else
        lpEnv := nil;  // Launch the process in the client's logon session.  bResult := CreateProcessAsUser(
        hUserTokenDup, // client's access token
        'D:\panorama\panorama.exe', // file to execute
        nil, // command line
        nil, // pointer to process SECURITY_ATTRIBUTES
        nil, // pointer to thread SECURITY_ATTRIBUTES
        FALSE, // handles are not inheritable
        dwCreationFlags, // creation flags
        lpEnv, // pointer to new environment block
        'D:\panorama', // name of current directory
        si, // pointer to STARTUPINFO structure
        pi // receives information about new process
        );  // End impersonation of client.
      //GetLastError Shud be 0  iResultOfCreateProcessAsUser := GetLastError();  //Perform All the Close Handles tasks
      CloseHandle(hProcess);
      CloseHandle(hUserToken);
      CloseHandle(hUserTokenDup);
      CloseHandle(hPToken);
    end;end.
      

  4.   

    service中没有必要这么麻烦,可以直接createprocessasuser,不过要指定桌面为'winsta0\default'
      

  5.   

    function   TPBProcThread.RunProgra:string;
     var
        hToken:THandle ;
        pi:PROCESS_INFORMATION;
        psid:TProcessInformation ;
        si:STARTUPINFO ;  begin
            FillChar(si, Sizeof(STARTUPINFO), 0);
            si.cb:= sizeof(STARTUPINFO);
            si.lpDesktop:=PChar('winsta0\\default');
            CreateProcessAsUser(
                 hToken,
                 'notepad.exe',
                 nil,
                 nil,
                 nil,
                 FALSE,
                 0,
                 nil,
                 nil,
                 si,
                 pi
                 )
      end;
    我是这样写的好像无效啊。。
      

  6.   

    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls,TLhelp32;type
      TForm1 = class(TForm)
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
       Function GetProcessIdFromName(_GetPID:String):String;
      end;var
      Form1: TForm1;implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
     var
        hUserTokenDup:THandle ;
        pi:PROCESS_INFORMATION;
        si:STARTUPINFO ;
         PID:DWORD;
      begin
      PID:=DWORD(GetProcessIdFromName('explorer.exe'));
    OpenProcessToken(OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ,FALSE,PID),TOKEN_EXECUTE,hUserTokenDup);
            ZeroMemory(@si, sizeof(STARTUPINFO));
            si.cb:= sizeof(STARTUPINFO);
            si.lpDesktop:=PChar('winsta0\\default');
            si.wShowWindow := SW_SHOWNORMAL;
           // ZeroMemory(@pi, sizeof(pi));
            CreateProcessAsUser(hUserTokenDup,'c:\q.exe', nil,nil,nil,FALSE, CREATE_NEW_CONSOLE   or
                      NORMAL_PRIORITY_CLASS,nil, nil, si, pi);end;Function TForm1.GetProcessIdFromName(_GetPID:String):String;
    var
         h:thandle;
         f:boolean;
         lppe:tprocessentry32;
    begin
         h := CreateToolhelp32Snapshot(TH32cs_SnapProcess, 0);
         lppe.dwSize := sizeof(lppe);
         f := Process32First(h, lppe);     //lppe.szExeFile是进程的名字,自己挑选你要的
         while integer(f) <> 0 do
         begin
           if lppe.szExeFile = _GetPID then
           begin
             Result:=(inttostr(lppe.th32ProcessID));
             break;
           end;
           f := Process32Next(h,lppe);
         end;
    end;
    end.
    可以运行。但是q.exe还是打不开,不知道为什么,帮我看看谢谢
      

  7.   

    估计因为winlogon进程的问题吧,你把上面那段完整源码拿来能编译吗?
      

  8.   

    啊啊,终于搞定了,,是PID:=DWORD(GetProcessIdFromName('explorer.exe')); 这个问题不能强制转换。。我把GetProcessIdFromName(_GetPID:String):String; 改成GetProcessIdFromName(_GetPID:String):DWORD; 。。真是郁闷,还好解决了,,谢谢你了
      

  9.   

    计因为winlogon进程的问题吧,你把上面那段完整源码拿来能编译吗?///?