Bonjour à tous,

Je cherche à faire qqchose d'archi classique : ouvrir un fichier et attendre que l'utilisateur ait fini pour revenir dans l'application. J'ai cherché à utiliser les moyens suivants :

ShellExecute: Rien à redire. On lui passe le nom d'un fichier quelque soit son type (Pdf, doc, jpg...), il trouve le programme associé et ouvre le fichier avec. Seul problème: dès que le programme en question est lancé, on poursuit l'exécution du code. Donc ca va pas dans mon cas.


CreateProcess + WaitForSingleObject: la on peut effectivement créer un processus et attendre qu'il soit terminé pour poursuivre. Seul problème: on ne peut lancer que des exécutables, et non pas des fichiers nus (que Windows se chargerait d'ouvrir avec le bon programme).
Voir exemple sur le site (que dis-je, la bible!) de Michel Bardou :

http://www.phidels.com/php/index.php...zip.php3&id=66

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
function LanceAppliAttenteFin(NomFichier:string):boolean;
{ LanceAppliAttenteFin renvoie true si le lancement s'est bien passé   }
var
  StartInfo : TStartupInfo;
  ProcessInformation : TProcessInformation;
begin
  result:=true;
  ZeroMemory(@StartInfo, sizeof(StartInfo)); // remplie de 0 StartInfo
  StartInfo.cb:=sizeof(StartInfo);
  if CreateProcess(nil,PChar(NomFichier),nil,nil,true,0,nil,nil,StartInfo,ProcessInformation)
  then WaitForSingleObject(ProcessInformation.hProcess, INFINITE)// attend que l'application désignée par le handle ProcessInformation.hProcess soit terminée
  else result:=false;
end;

ShellExecuteEx: Différence avec ShellExecute: on peut récupérer l'id du process. Du coup, après avoir demandé à Windows d'ouvrir le fichier souhaité, on peut attendre que le process soit terminé. Le parfait mariage entre la 1ere et la 2eme méthode. Mais léger problème: le "scan" d'attente de fin de process prend 100% des ressources du CPU.

Méthode utilisée : http://delphi.about.com/od/windowssh...uteprogram.htm

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
uses ShellApi;
...
var
   SEInfo: TShellExecuteInfo;
   ExitCode: DWORD;
   ExecuteFile, ParamString, StartInString: string;
begin
   ExecuteFile:='c:\temp\monfichier.pdf';
 
   FillChar(SEInfo, SizeOf(SEInfo), 0) ;
   SEInfo.cbSize := SizeOf(TShellExecuteInfo) ;
   with SEInfo do begin
     fMask := SEE_MASK_NOCLOSEPROCESS;
     Wnd := Application.Handle;
     lpFile := PChar(ExecuteFile) ;
{
ParamString can contain the
application parameters.
}
// lpParameters := PChar(ParamString) ;
{
StartInString specifies the
name of the working directory.
If ommited, the current directory is used.
}
// lpDirectory := PChar(StartInString) ;
     nShow := SW_SHOWNORMAL;
   end;
   if ShellExecuteEx(@SEInfo) then begin
     repeat
       Application.ProcessMessages;
       GetExitCodeProcess(SEInfo.hProcess, ExitCode) ;
     until (ExitCode <> STILL_ACTIVE) or
Application.Terminated;
     ShowMessage('Fichier PDF fermé') ;
   end
   else ShowMessage('Impossible de visionner le fichier PDF!') ;
end;
Cette dernière méthode est assez séduisante, mais alors le fait que le processeur soit pris a 100% pendant la boucle repeat ..until est loin d'être satisfaisant.

Est-ce que quelqu'un voit un moyen de rendre cette boucle moins gourmande ? J'avais pensé mettre un sleep(1000) dans la boucle, mais je ne trouve pas ca très élégant ?