Newsgroup: it.comp.lang.delphi
Titolo: Lanciare applicazione dotnet da un programma win32

Tramite la funzione postata giorni fa (
http://snipurl.com/1ock0
), sono in
grado di avere launcher per una pipe di processi.
Il problema ora č che mi hanno passato un programma .net compilato con c#,
e la createprocess ovviamente fallisce restituendo in quanto il programma
non e' un applicativo win32 valido.
Esiste qualche modo di gestire questo problema?
Intendo dire, un pezzo di codice da compilare in win32, che lanci un
programma .net e ne aspetti il termine catturandone l'RC...
Any idea?
TIA.
-- 
Morde

non e' un applicativo win32 valido.
L'installazione del framework dovrebbe modificare il loader per caricare 
correttamente ed eseguire i programmi .NET.
Da linea comando con RUNAS riesci ad eseguirlo?
--- posted by geoForum on 
http://www.delphiedintorni.it

 Da linea comando con RUNAS riesci ad eseguirlo?
Sono su winxp e sviluppo in win32 con D7 (non 2007, proprio 7).
Il programma da sè viene eseguito tranquillamente, il problema e' che una
volta lanciato, il flusso applicativo continua immediatamente, e' come se
windows un processo separato e indipendente da quello che l'ha invocato.
Io ho necessità di aspettare che questo programma termini perchè, essendo
lo stesso parte di una pipe, il suo output diventa l'input del successivo.
il codice che dimostra questo è semplice:
procedure TForm1.Button4Click(Sender: TObject);
var
   SEInfo: TShellExecuteInfo;
   ExitCode: DWORD;
   ExecuteFile, ParamString, StartInString: string;
begin
   ExecuteFile:='C:\TEMP\publish\publish\GenericMapping.application';
   FillChar(SEInfo, SizeOf(SEInfo), 0) ;
   SEInfo.cbSize := SizeOf(TShellExecuteInfo) ;
   with SEInfo do begin
     fMask := SEE_MASK_NOCLOSEPROCESS;
     Wnd := Application.Handle;
     lpFile := PChar(ExecuteFile) ;
     nShow := SW_SHOWNORMAL;
   end;
   if ShellExecuteEx(@SEInfo) then begin
     repeat
       Application.ProcessMessages;
       GetExitCodeProcess(SEInfo.hProcess, ExitCode) ;
     until (ExitCode <> STILL_ACTIVE) or
            Application.Terminated;
     ShowMessage('terminated') ;
   end
   else ShowMessage('Error !') ;
end;
Come clicco sul pulsante, la message "terminated" appare immediatamente e
il programma .net continua imperterrito fino alla chiusura.
-- 
Morde

      until (ExitCode <> STILL_ACTIVE) or
Non hai bisogno di ciclare in questo modo. Usa WaitForSingleObject().
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 Non hai bisogno di ciclare in questo modo. Usa WaitForSingleObject().
   if ShellExecuteEx(@SEInfo) then
     begin
        WaitForSingleObject(seinfo.hProcess, INFINITE);
        ShowMessage('terminated') ;
     end
   else ShowMessage('Error !') ;
Non funziona ancora, si comporta come prima della modifica: esce subito.
Ritorna "terminated" ma il processo .net e' ancora in corso.
-- 
Morde

 Ritorna "terminated" ma il processo .net e' ancora in corso.
Hummm... probabilmente perché viene eseguito da un launcher che inizia e
termina... che cosa vedi nella lista dei processi? c'č il nome di
un'immagine?


"Morde" ha scritto nel messaggio

Prova questa (la uso con applicazioni Win32 ma funziona anche con l'unico
programma .NET che ho sottomano):
function WinExecAndWait32V2( const FileName, CurrDir: string;
Visibility: integer ): DWORD;
{ V1 by Pat Ritchey, V2 by P.Below }
   procedure WaitFor( processHandle: THandle );
      var
         msg: TMsg;
         ret: DWORD;
      begin
         repeat
            ret := MsgWaitForMultipleObjects(
                      1,             { 1 handle to wait for }
                      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 message, process paint messages only. Calling
  PeekMessage gets messages sent 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
      zAppName:    array[ 0..512 ] of char;
      zAppPath:    array[ 0..512 ] of char;
      StartupInfo: TStartupInfo;
      ProcessInfo: TProcessInformation;
      {ProHandle: THandle;}
      Buf1, Buf2: array[ 0..80 ] of char;
   begin{ WinExecAndWait32V2 }
      StrPCopy( zAppName, FileName );
      StrPCopy( zAppPath, CurrDir );
      FillChar( StartupInfo, SizeOf(StartupInfo), $00 );
      StartupInfo.cb := SizeOf(StartupInfo);
      StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
      StartupInfo.wShowWindow := Visibility;
      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 environment block }
          zAppPath,                 { 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;
   end;{ WinExecAndWait32V2 }
Usata cosi':
if WinExecAndWait32V2('C:\Programmi\Paint.NET\PaintDotNet.exe',
'C:\Programmi\Paint.NET', 1) = 0
 then ShowMessage('terminated')
 else ShowMessage('Error !') ;
Ciao
-- 
ACSH
[TurboDelphi]
Chi fa da se', fatica il doppio

 un'immagine?
Hai ragione: vedo che sale in memoria questo processo:
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\dfsvc.exe
poi è lui che lancia il mio programma.
Ma subito dopo che dfsvc.exe è partito, il mio programma delphi che lo ha
lanciato prosegue mostrando il messaggio di "terminated"..
Any idea?
-- 
Morde

  else ShowMessage('Error !') ;
Anche a me si ferma ad aspettare... è l'altro programma che si comporta
diversamente essendo lanciato tramite un launcher, dfsvc.exe, del framework
.net. :-//
-- 
Morde

>diversamente essendo lanciato tramite un launcher, dfsvc.exe, del 
AFAIK dfsvc.exe č il launcher per le applicazioni "ClickOnce" di NET 
2.0, ma che estensione ha l'eseguibile, ".application"? In questo caso 
temo che il problema sia che per essere lanciato l'eseguibile passa per 
una serie di indirezioni.


 ma che estensione ha l'eseguibile, ".application"?
Si infatti.
Ho risolto facendomi dare i sorgenti e ricompilandoli con visual studio
express: ora ho un .exe che si comporta come dovrebbe.
Grazie anche ad andrea e acsh :-)
-- 
Morde

>2.0, ma che estensione ha l'eseguibile, ".application"? In questo caso 
Ah sì, vedo nel codice che è esattamente così - il problema è che non è 
un "normale" eseguibile .NET, ma il deployment manifest file per 
un'applicazione ClickOnce, che non è altro che il solito file XML con le 
informazioni per raggiungere ed eseguire l'applicazione .NET.
Dfsvc.exe è registrato per "eseguire" i .application, e quello che fa è 
leggere le informazioni dal file XML e quindi eseguire l'applicazione, 
purtroppo tu vedi questo processo terminare, mentre il processo .NET che 
lancia rimane in esecuzione.
Potresti provare ad enumerare i processi figli per "acchiappare" il 
processo che ti interessa.
