Lancer une application windows depuis un service DELPHI

Signaler
Messages postés
2
Date d'inscription
lundi 31 mai 2004
Statut
Membre
Dernière intervention
27 avril 2009
-
Messages postés
2
Date d'inscription
lundi 31 mai 2004
Statut
Membre
Dernière intervention
27 avril 2009
-
Bonjour,

je n'arrive pas, malgrè tous les conseils et exemples que j'ai pu lire, à relancer une application depuis un service.

Ma problèmatique est la suivante. Une application windows (écrite en DELPHI) doit tourner toute la journée pour réceptionner des flux et mettre à jour automatiquement une base de données. Cette application ne peut pas être un service pour des raisons diverses. Elle gère un log des entrées de flux (affichage continu) et le traitement dans la base se fait lui via un thread. Il arrive qu'en cas d'erreur d'écriture, cette application se ferme d'elle-même. Il faut donc pouvoir la relancer. D'où l'idée d'un service qui va vérifier si l'application tourne et la relancer le cas échéant.

Mais c'est là que le problème arrive. Soit il ne se passe rien ..., soit l'application démarre pour se refermer aussitôt, soit elle apparaît dans les processus windows, mais pas dans les applications, et elle ne tourne pas ... J'ai essayé diverses choses : Interactive à true dans le service, droit d'intéragir avec le bureau dans la gestion des services windows, lancement du service dans le compte local du poste pour que le propriétaire ne soit pas SYSTEM, passer par une commande dos (.bat), ... , placé des logs partout pour voir ce qui se passe, ... rien à faire ! (Sauf si l'application se nomme notapad.exe ... là ça fonctionne mais bon, ce n'est pas non plus le but du service ).

Juste une info complémentaire avant de laisser la place au bout de code avec les différentes méthodes que j'ai utilisées, au lancement mon application affiche un écran splash qui, selon un paramètre dans la base de registre doit présenter une image. Or, les rares fois où l'application se lance pour se refermer aussitôt, cette image n'est pas celle prévue par le paramètre mais celle par défaut quant ce paramètre est absent.

Merci d'avance de l'aide que vous pourrez m'apporter.
Bonne journée.

"The code" :

procedure Verifier(Sender: TObject);
var SnapShot      : Cardinal;
      ProcessEntry : TProcessEntry32;
      Trouve          : boolean;
      UINT            : integer;
      StartInfo        : TStartupInfo;
      ProcessInfo   : TProcessInformation;
      cExe              : array [0..255] of Char;
      sExe              : string;
      pcFile            : PChar;
begin
  
// Recherche si le programme passé dans ProgLire est en cours d'éxecution
   SnapShot          := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
   if SnapShot = 0 then Exit;
   ProcessEntry.dwSize := SizeOf(ProcessEntry);
   Trouve              := false;
   if Process32First(SnapShot, ProcessEntry) then
   begin
      if ProcessEntry.szExeFile = ProgLire then
         Trouve        := true
      else begin
         while Process32Next(SnapShot, ProcessEntry) do
         begin
            if ProcessEntry.szExeFile = ProgLire then
               Trouve  := true;
         end;
      end;
      CloseHandle(SnapShot);
   end;
   // Si le programme à contrôler (ProgLire) n'existe pas, le lancer
   if not Trouve then
   begin
      // Méthode une - ProgLance contient le nom (répertoire/file.exe) du pgm à relancer
       FindExecutable(PChar(ExtractFileName(ProgLance)), PChar(ExtractFilePath(ProgLance)), cExe);
       sExe:= string(cExe);
       if UpperCase(ExtractFileName(sExe)) <> UpperCase(ExtractFileName(ProgLance)) then
              pcFile :=PChar(' "' + ProgLance + '"')
       else pcFile := nil;
      
ZeroMemory(@StartInfo, SizeOf(StartInfo));
       with StartInfo do
       begin
         cb                      := SizeOf(StartInfo);
         dwFlags             := STARTF_USESHOWWINDOW;
         wShowWindow := SW_SHOW;
       end;

       if not CreateProcess(PChar(ExtractFileName(sExe)), pcfile, nil, nil, false,
                                      VarArrayOf ([CREATE_NEW_PROCESS_GROUP, HIGH_PRIORITY_CLASS,
                                                            DETACHED_PROCESS]), nil, nil, StartInfo, ProcessInfo) then
            writeln(Fic, '*** erreur d''éxecution ' + IntToStr(GetLastError())); // Ecrire textfile code erreur

        // Variante 1
        // if not CreateProcess(PChar(ExtractFileName(sExe)), pcfile, nil, nil, false, 0, nil, nil, StartInfo, ProcessInfo)
        // then ... ecrire erreur

       // Variante 2

       // ShellExecute(0, 'open',Pchar(ProgLance),nil,
       //                     PChar(ExtractFileNameProgLance)),SW_SHOWDEFAULT);

        // Variante 3
        // WinExec(PChar(ProgLance), SW_SHOWDEFAULT);
end;

2 réponses

Messages postés
2226
Date d'inscription
dimanche 5 octobre 2003
Statut
Modérateur
Dernière intervention
18 novembre 2010
13
Salut

L'exécutable doit être lancé depuis le dossier ou il se trouve. J'imagine que le fameux paramètre non trouvé qui fait apparaitre un splash par défaut se trouve dans un .ini ?

Ton createprocess ou ton shellexecute sont tout simplement mal paramétré à mon avis.

Voici msdn pour CreateProcess :




BOOL WINAPI CreateProcess(
  __in_opt     LPCTSTR lpApplicationName,
  __inout_opt  LPTSTR lpCommandLine,
  __in_opt     LPSECURITY_ATTRIBUTES lpProcessAttributes,
  __in_opt     LPSECURITY_ATTRIBUTES lpThreadAttributes,
  __in         BOOL bInheritHandles,
  __in         DWORD dwCreationFlags,
  __in_opt     LPVOID lpEnvironment,
  __in_opt     LPCTSTR lpCurrentDirectory,
  __in         LPSTARTUPINFO lpStartupInfo,
  __out        LPPROCESS_INFORMATION lpProcessInformation
);



Et toi :

CreateProcess(PChar(ExtractFileName(sExe)), pcfile, nil, nil, false, 0, nil, nil, StartInfo, ProcessInfo)


au lieu de :

CreateProcess(PChar(ExtractFileName(sExe)), pcfile, nil, nil, false, 0, nil, PChar(
ExtractFilePath(sExe)

), StartInfo, ProcessInfo)






Voici MSDN pour ShellExecute :


HINSTANCE ShellExecute(      
    HWND hwnd,
    LPCTSTR lpOperation,
    LPCTSTR lpFile,
    LPCTSTR lpParameters,

    LPCTSTR lpDirectory,


    INT nShowCmd
);
Et toi :

ShellExecute(0, 'open',Pchar(ProgLance),nil,PChar(ExtractFileNameProgLance)),SW_SHOWDEFAULT);


au lieu de

ShellExecute(0, 'open',Pchar(ProgLance),nil,PChar(ExtractFilePath(ProgLance))),SW_SHOWDEFAULT);




Voici SMDN pour WinExec :
This function is provided only for compatibility with 16-bit Windows.
Tu es en 32 bits non ? Evite ^^

Essaie avec ça et tiens nous au courant !
Messages postés
2
Date d'inscription
lundi 31 mai 2004
Statut
Membre
Dernière intervention
27 avril 2009

Merci de cette réponse. Il est trop tard ce soir pour faire un essai mais je m'y lance bientôt ...


Je ne manquerais pas de revenir donner le résultat ici ... à bientôt