IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

API, COM et SDKs Delphi Discussion :

Surveiller une application externe


Sujet :

API, COM et SDKs Delphi

  1. #1
    Nouveau membre du Club
    Inscrit en
    Octobre 2011
    Messages
    33
    Détails du profil
    Informations forums :
    Inscription : Octobre 2011
    Messages : 33
    Points : 27
    Points
    27
    Par défaut Surveiller une application externe
    Bonjour à tous.
    Le bout de code que j'ai écrit me permet d'arrêter une application externe qui est en train de tourner grâce à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    H := FindWindow(nil, 'la fenetre de mon appli');
        if H <> 0 then PostMessage(H, WM_CLOSE, 0, 0);
    Le problème, c'est qu'il faut que cette application soit lancée et que je connaisse le nom exact de la fenêtre ouverte, ce qui est parfois difficile. Par exemple, le programme 'Photoshop.exe' ouvre une fenêtre qui s'appelle 'Adobe Photoshop CC 2015'.
    Mon appli Delphi doit 'surveiller' plusieurs applications dont le nom de l'exe fait partie d'une ListBox et lancer ou arrêter certains d'entre eux en fonction de critères bien définis.
    Bref, comment expliquer que si 'MonAppli.exe' est lancée, je dois la fermer. ("MonAppli.exe" étant le nom de l'executable tel qu'il apparaît dans le dossier d'installation de cette appli et qui, souvent, n'est pas celui de la fenêtre ouverte)
    Suis-je clair ?

    Merci de me donner une piste.

    a+

  2. #2
    Expert éminent
    Avatar de Lung
    Profil pro
    Analyste-programmeur
    Inscrit en
    Mai 2002
    Messages
    2 664
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste-programmeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 2 664
    Points : 6 967
    Points
    6 967
    Par défaut
    J'ai déjà fait la correspondance entre un processus et ses fenêtres.
    Voici un bout de code bricolé pour te donner une piste (pas testé):
    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
    39
    40
    41
    42
    43
    44
    uses ShellAPI
     
    // Pour chercher un processus par le nom de l'exe.
     
    procedure TFormProcessus.EnumProcessus;
    var
       nSnapShot: Integer;
       ProcessEntry: TProcessEntry32;
    begin
       nSnapShot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
     
       // Si erreur.
       if nSnapShot = -1 then
          Exit;
       try
          ProcessEntry.dwSize := SizeOf(ProcessEntry);
     
          // Lecture du premier processus de la liste.
          if Process32First(nSnapShot, ProcessEntry) then
          begin
             if ProcessEntry.szExeFile = 'le fichier exe que je cherche' then
             begin
                // Trouvé :  recherche des fenêtres avec le ProcessEntry.th32ProcessID ...
     
     
                Exit;
             end;
     
             // Tant qu'il reste un processus.
             while Process32Next(nSnapShot, ProcessEntry) do
             begin
                if ProcessEntry.szExeFile = 'le fichier exe que je cherche' then
                begin
                   // Trouvé :  recherche des fenêtres avec le ProcessEntry.th32ProcessID ...
     
     
                   Exit;
                end;
             end;
          end;
       finally
          CloseHandle(nSnapShot);
       end;
    end;
    Pour chercher les fenêtres par le Pid du processus :
    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
    function EnumWindowsProc(Wnd: HWND; lParam: lParam): BOOL;   stdcall;
    var
       Param: Integer;
       cPid: Cardinal;
    begin
       Result := True;
     
       // Recherche.
       GetWindowThreadProcessID(Wnd, @cPid);
       if MonPID = cPid then
       begin
          // Plus qu'à envoyer le message à la fenêtre ...
     
          Param := 0;
       end;
    end;
     
    // Appel.
    nParam := 0;
    EnumWindows(@EnumWindowsProc, nParam);
    L'urgent est fait, l'impossible est en cours, pour les miracles prévoir un délai. ___ Écrivez dans un français correct !!

    C++Builder 5 - Delphi 6#2 Entreprise - Delphi 2007 Entreprise - Delphi 2010 Architecte - Delphi XE Entreprise - Delphi XE7 Entreprise - Delphi 10 Entreprise - Delphi 10.3.2 Entreprise - Delphi 10.4.2 Entreprise - Delphi 11.1 Entreprise
    OpenGL 2.1 - Oracle 10g - Paradox - Interbase (XE) - PostgreSQL (15.4)

  3. #3
    Membre averti
    Homme Profil pro
    Ingénieur développement en retraite
    Inscrit en
    Juin 2002
    Messages
    401
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 71
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement en retraite
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Juin 2002
    Messages : 401
    Points : 300
    Points
    300
    Par défaut
    Pour faire ce que tu veux, moi j'utilise cette procédure qui fonctionne bien.
    Ce n'est pas moi qui l'ai écrite, mais je ne sais plus exactement où je l'ai trouvée.
    Il y a une référence à son auteur dans les commentaires.

    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
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
     
    function ExeRunning(NomApplication : string; StopProcess:Boolean):Boolean;
    //Test si une application est en cours d'exécution
    // StopProcess indique si on termine l'application 'NomApplication'
     
    // Code proposé par Thunder_nico
     
    var
       ProcListExec : TProcessentry32;
       PrhListExec : Thandle;
       Continu : Boolean;
       isStarted : Boolean;
       HandleProcessCourant : Cardinal;
       PathProcessCourant : string;
       ProcessCourant :String;
     
    begin
         result:=False;
         if NomApplication='' then Exit;
         // Liste des applications en cours d'exécution
         // Initialisation des variables et récuperation de la liste des process
         ProcListExec.dwSize:=sizeof(ProcListExec);
         Continu := True;
         isStarted := False;
     
         Try
             // Récupére la liste des process en cours d'éxécution au moment de l'appel
            PrhListExec:=CreateToolhelp32Snapshot(TH32CS_SNAPALL,0);
            if (PrhListExec <> INVALID_HANDLE_VALUE)
             then
             begin
              //On se place sur le premier process
              Process32First(PrhListExec,ProcListExec);
     
                // Tant que le process recherché n'est pas trouvé et qu'il reste
                // des process dans la liste, on parcourt et analyse la liste
              while Continu do
              begin
                ProcessCourant := Uppercase(ProcListExec.szExeFile);
                isStarted := (ProcessCourant = Uppercase(ExtractFileName(NomApplication)));
                if isStarted then
                 begin
                  HandleProcessCourant := ProcListExec.th32ProcessID;
                  PathProcessCourant := ExtractFilepath(ProcListExec.szExeFile);
                  Continu := False;
                 end
                else // Recherche le process suivant dans la liste
                  Continu := Process32Next(PrhListExec,ProcListExec);
              end;
     
              if StopProcess
               then
                if isStarted then
                 begin  // Termine le process en indiquant le code de sortie zéro
                  TerminateProcess(OpenProcess(PROCESS_TERMINATE,False,HandleProcessCourant),0);
                  Sleep(500); // Laisse le temps au process en cours de suppression de s'arrêter
                 end;
            end;
         Finally
            CloseHandle(PrhListExec); // Libére les ressources
            Result := isStarted;
         end;
    end;

  4. #4
    Nouveau membre du Club
    Inscrit en
    Octobre 2011
    Messages
    33
    Détails du profil
    Informations forums :
    Inscription : Octobre 2011
    Messages : 33
    Points : 27
    Points
    27
    Par défaut
    Citation Envoyé par Bernard B Voir le message
    Pour faire ce que tu veux, moi j'utilise cette procédure qui fonctionne bien.


    Génial ! Un bout de code qui fait parfaitement le job !!

    Merci à toi et à Thunder_nico.

    Merci Lung, ton code est très intéressant et je le garde sous le coude ...

  5. #5
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 693
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 693
    Points : 13 126
    Points
    13 126
    Par défaut
    Attention à cette ligne TerminateProcess(OpenProcess(PROCESS_TERMINATE,False,HandleProcessCourant),0), le handle retourné par OpenProcess doit être libéré par CloseHandle. De plus, WaitForSingleObject sur ce handle remplacerait avantageusement ce Sleep(500) qui ne garantit en tout cas pas que le processus est bien arrêté à la sortie de la fonction (si tel est le souhait)

    A noter aussi que ExtractFilepath(ProcListExec.szExeFile) renverra toujours une chaîne vide, szExeFile ne contient que le nom de l'exe.

    Et comme pour toute les fonctions First/Next, on écrirait plutôt la boucle ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    if Process32First(...) then
    repeat
       ...
    until not Process32Next(...);

  6. #6
    Nouveau membre du Club
    Inscrit en
    Octobre 2011
    Messages
    33
    Détails du profil
    Informations forums :
    Inscription : Octobre 2011
    Messages : 33
    Points : 27
    Points
    27
    Par défaut Eureka !
    Avec votre aide, voila la solution (qui marche nickel pour moi)

    Pour trouver l'ID du process en fonction du nom de l'exe :

    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
    //------- Entree : Nom de l'executable : Sortie : ID du process, 0 si non trouvé  ---------------------
    Function GetProcessID(NomExe : String) : Cardinal;
    var
       ProcListExec : TProcessentry32;
       PrhListExec : Thandle;
     
    Begin
        ProcListExec.dwSize := sizeof(ProcListExec);
        PrhListExec := 0;
        Result := 0;
     
        Try
            PrhListExec := CreateToolhelp32Snapshot(TH32CS_SNAPALL,0);
            if (PrhListExec <> INVALID_HANDLE_VALUE) then
            begin
                // Parcourt la liste des process à la recherche de 'NomExe'
                if Process32First(PrhListExec, ProcListExec) then
                Repeat
                    If Uppercase(ProcListExec.szExeFile) = Uppercase(NomExe) then // trouvé !
                    Begin
                        Result := ProcListExec.th32ProcessID; // Retourne le process ID
                        break;
                    End;
                Until not (Process32Next(PrhListExec,ProcListExec));
            end;
        Finally
            CloseHandle(PrhListExec);
        end;
    End;
    Ensuite, pour terminer proprement le process :

    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
     
    [...]
    Var
      HProcess : THandle;
      Process : cardinal;
     
    [...]
     
    Process := GetProcessID('Notepad++.exe'); // ... par exemple
    if Process > 0 then
    try
    	HProcess := OpenProcess(PROCESS_TERMINATE, False, Process); // Demande d'accés à la propriété TERMINATE du process
    	TerminateProcess(HProcess,0);                               // Termine le process
    	WaitForSingleObject(HProcess, INFINITE);                    // Attend (infiniment !) que le process se termine proprement
    Finally
    	CloseHandle(HProcess);
    end;
    La vie est belle !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 12
    Dernier message: 23/01/2008, 09h17
  2. Fermer une application externe
    Par jean tof dans le forum C++Builder
    Réponses: 2
    Dernier message: 02/05/2006, 16h18
  3. [Système][Runtime]lancer une application externe
    Par mencaglia dans le forum API standards et tierces
    Réponses: 14
    Dernier message: 22/09/2005, 17h27
  4. Réponses: 6
    Dernier message: 07/09/2005, 20h31
  5. [Excel] Utiliser une application externe par une macro
    Par thierry2.dlp dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 09/08/2005, 22h07

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo