Newsgroup: it.comp.lang.delphi
Titolo: Lanciare un processo da un servizio

Nonostante le numerose ricerche e presunte soluzioni trovate a riguardo,
non riesco a uscire da una situazione di questo tipo: ho realizzato un
servizio che, nel verficarsi di un determinato evento trappato da un
componente, deve eseguire uno o piu' processi a catena, catturandone il
result code.
Ho trovato molti pezzi di codice a riguardo, ma tutto quello che ottengo e'
che mi viene lanciato il processo in memoria e non riesco ad averlo sul
desktop. Ho provato con il classico notepad.exe, ma una volta lanciato si
vede dal task manager ma non posso interagire con esso in quanto non e'
presente nella lista delle applicazioni attive (alt+tab).
Vi giro il pezzo di codice (trovato su torry) che utilizzo per fare lo
spawn del processo e che non mi funziona.
La funzione viene chiamata con:
result :=
trunc(WinExecAndWait32V2('c:\windows\notepad.exe',SW_SHOWNORMAL));
In quella che segue ho aggiunto questa istruzione:
StartupInfo.lpDesktop := PCHAR('WinSta0/Default');
per poter visualizzare il notepad, senza risultati.
Il notepad resta nell'elenco dei processi ma non posso interagire con esso.
{--WinExecAndWait32V2 ------------------------------------------------}
{: Executes a program and waits for it to terminate
@Param FileName contains executable + any parameters
@Param Visibility is one of the ShowWindow options, e.g. SW_SHOWNORMAL
@Returns -1 in case of error, otherwise the programs exit code
@Desc In case of error SysErrorMessage( GetlastError ) will return an
  error message. The routine will process paint messages and messages
  send from other threads while it waits.
}{ Created 27.10.2000 by P. Below
-----------------------------------------------------------------------}
function TSPReceiverService.WinExecAndWait32V2(FileName: string;
Visibility: Integer): DWORD;
  procedure WaitFor(processHandle: THandle);
  var
    Msg: TMsg;
    ret: DWORD;
  begin
    repeat
      ret := MsgWaitForMultipleObjects(1, { 1 handle to wait on }
        processHandle, { the handle }
        False, { wake on any event }
        INFINITE, { wait without timeout }
        QS_PAINT or { wake on paint messages }
        QS_SENDMESSAGE { or messages from other threads }
        );
      if ret = WAIT_FAILED then Exit; { can do little here }
      if ret = (WAIT_OBJECT_0 + 1) then
      begin
          { Woke on a message, process paint messages only. Calling
            PeekMessage gets messages send from other threads processed. }
        while PeekMessage(Msg, 0, WM_PAINT, WM_PAINT, PM_REMOVE) do
          DispatchMessage(Msg);
      end;
    until ret = WAIT_OBJECT_0;
  end; { Waitfor }
var { V1 by Pat Ritchey, V2 by P.Below }
  zAppName: array[0..512] of char;
  StartupInfo: TStartupInfo;
  ProcessInfo: TProcessInformation;
begin { WinExecAndWait32V2 }
  StrPCopy(zAppName, FileName);
  FillChar(StartupInfo, SizeOf(StartupInfo), #0);
  StartupInfo.cb          := SizeOf(StartupInfo);
  StartupInfo.dwFlags     := STARTF_USESHOWWINDOW;
  StartupInfo.wShowWindow := Visibility;
  StartupInfo.lpDesktop := PCHAR('WinSta0/Default');
  if not CreateProcess(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 }
    nil, { pointer to current directory name }
    StartupInfo, { pointer to STARTUPINFO }
    ProcessInfo) { pointer to PROCESS_INF } then
    Result := DWORD(-1) { failed, GetLastError has error code }
  else
  begin
    Waitfor(ProcessInfo.hProcess);
    GetExitCodeProcess(ProcessInfo.hProcess, Result);
    CloseHandle(ProcessInfo.hProcess);
    CloseHandle(ProcessInfo.hThread);
  end; { Else }
end; { WinExecAndWait32V2 }
-- 
Morde

Pre-Vista, se il processo gira come SYSTEM e ha il flag "Consenti al 
servizio di interagire con il desktop" non dovresti avere problemi. Se 
perň il servizio gira con un altro utente allora non č detto che 
quell'utente abbia il permesso di accedere al desktop corrente - devi 
far sě che il servizio impersoni l'utnete e acceda al suo desktop.
Da Vista in poi i servizi girano comunque in un desktop separato, quindi 
devi comunque accedere al desktop dell'utente.
--- posted by geoForum on 
http://www.delphiedintorni.it

 servizio di interagire con il desktop" non dovresti avere problemi.
Purtroppo è proprio così: il servizio gira come system è ha la proprietà di
interazione col desktop abilitata...
Sto testando con un programma di tipo applicazione (e non servizio) e non
riesco lo stesso a vedere il notepad.. probabilmente non funziona proprio
il tip :-//
-- 
Morde

 il tip :-//
Infatti bastava modificare i creation flags,
togliendo CREATE_NEW_CONSOLE
sostituendolo con CREATE_NEW_PROCESS_GROUP
il tutto ha funzionato.
Grazie Stefano per le indizazioni "vista compliant" :-)
ciao
-- 
Morde