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

C++Builder Discussion :

probleme de recupération de handle


Sujet :

C++Builder

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    22
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 22
    Par défaut probleme de recupération de handle
    Bonjour,

    Je travaille sur BCB6 sous XP.

    Dans mon appli je voudrai lancer une page WEB. puis pouvoir la fermer.
    le handle de process que je recupére aprés un shellexecuteex est NULL.
    je ne comprend pas pourquoi.

    Code ci joint :

    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
    SHELLEXECUTEINFO exe;
     
    void __fastcall TForm1::Button4Click(TObject *Sender)
    {
    exe.cbSize = sizeof(exe);
    exe.fMask = SEE_MASK_NOCLOSEPROCESS;
    exe.hwnd = NULL;
    exe.lpVerb = "open";
    exe.lpFile = "http://www.fipradio.fr/player";
    exe.lpParameters = NULL;
    exe.lpDirectory = NULL;
    exe.nShow = SW_SHOW;
    exe.hInstApp = NULL;
    ShellExecuteEx(&exe);
    }
    //-------------------------------------------------------------------------
     
    void __fastcall TForm1::Button5Click(TObject *Sender)
    {
      if(exe.hProcess)
      { TerminateProcess(exe.hProcess,NULL);
        CloseHandle(exe.hProcess);
      }
    }
    Si quelqu'un peu m'expliquer pourquoi

    Cordialement

    EricNo

  2. #2
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 089
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 089
    Par défaut
    essaye
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    exe.lpFile = "iexplore http://www.fipradio.fr/player";
    ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    exe.lpFile = "firefox http://www.fipradio.fr/player";
    il est possible qu'en exploitant juste l'association shell cela ne fournisse pas de handle
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  3. #3
    Membre expérimenté
    Homme Profil pro
    Enseignant
    Inscrit en
    Mars 2012
    Messages
    164
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2012
    Messages : 164
    Par défaut
    Intéressant ton bug, EricNO. Peut-être es-tu tombé là-dessus:

    http://blogs.msdn.com/b/oldnewthing/...05/590749.aspx

    J'ai bien aimé ce passage:

    "First, as we noted, the HINSTANCE that you get from the ShellExecute function is useless. You have to use the ShellExecuteEx function and set the SEE_MASK_NOCLOSEPROCESS flag in the SHELLEXECUTEINFO structure, at which point a handle to process is returned in the hProcess member, But that still doesn't work."

    Et la conclusion:

    "There is no uniform way to detect that a document has been closed. Each program handles it differently. "

    Hâte de voir la solution*!

    * après coup, j'en voie une (EnumProcesses), je vais tester ça.

  4. #4
    Rédacteur
    Avatar de blondelle
    Homme Profil pro
    Inscrit en
    Mars 2006
    Messages
    2 738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 738
    Par défaut
    Salut EricNO
    A l'aide de Spy++ j'ai verifie le Handle renvoye par la fenetre qui s'ouvre
    Je recupere le Handle de cette facon
    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
     
    exe.cbSize = sizeof(exe);
    exe.fMask = SEE_MASK_NOCLOSEPROCESS;
    exe.hwnd = NULL;
    exe.lpVerb = "open";
    exe.lpFile = "<a href="http://www.fipradio.fr/player" target="_blank">http://www.fipradio.fr/player</a>";
    exe.lpParameters = NULL;
    exe.lpDirectory = NULL;
    exe.nShow = SW_SHOW;
    exe.hInstApp = NULL;
    ShellExecuteEx(&exe);
     
     
    Sleep(1000);
    hwnd = FindWindow("IEFrame", "fip - direct - Mercredi 21 Mars 11:54:15 - Windows Internet Explorer");
    hwnd = FindWindow("IEFrame", NULL);
    j'ai mis une tempo et repete deux fois FindWindow sinon on ne recupere pas le bon Handle, ce n'est pas tres propre, mais c'est peut etre un debut de piste
    si tu utilise ce code il faudra reconstruire la date dans le code "Mercredi 21 Mars 11:54:15" avant appel

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    22
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 22
    Par défaut un peu d'avancé
    Avec le code suivant j'arrive à récuperer le handle du process à condition qu'une fenetre IE ne soit pas déja ouverte.

    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
    void __fastcall TForm1::Button4Click(TObject *Sender)
    {
    exe.cbSize = sizeof(exe);
    exe.fMask = SEE_MASK_NOCLOSEPROCESS;
    exe.hwnd = NULL;
    exe.lpVerb = "open";
    exe.lpFile = "iexplore";
    exe.lpParameters = "http://www.fipradio.fr/player";
    exe.lpDirectory = NULL;
    exe.nShow = SW_SHOW;
    exe.hInstApp = NULL;
    ShellExecuteEx(&exe);
    }
    //-------------------------------------------------------------------------
     
    void __fastcall TForm1::Button5Click(TObject *Sender)
    {
      if(exe.hProcess)
      { TerminateProcess(exe.hProcess,NULL);
        CloseHandle(exe.hProcess);
      }
    }
    Au lieu de travailler sur le handle du process, n'y aurait il pas après un shellexecueex une fonction pour recuperer l'ID du process et une autre fonction pour tuer le process avec son ID ?

    Merci par avance

    EricNO

  6. #6
    Rédacteur
    Avatar de blondelle
    Homme Profil pro
    Inscrit en
    Mars 2006
    Messages
    2 738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 738
    Par défaut
    Si ton programme doit juste ouvrir et fermer ta page Web il est possible d'utiliser Ole
    le code
    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
     
    //---------------------------------------------------------------------------
    #include <vcl.h>
    #pragma hdrstop
    #include "Unit1.h"
    #include <utilcls.h> // <----- ne pas oublier
    #include <ComObj.hpp> // <----- utile dans certains cas
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TForm1 *Form1;
    Variant vMSIEApp;
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
            : TForm(Owner)
    {
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
    // demarrer IE
    // Cree un objet unique non initialisé de la classe spécifiée
    // par le paramètre 'InternetExplorer.Application'
    try
      {
    // ici en mode debug une exeption est levee c'est un fonctionnement 
    // normal, afin d'eviter d'ouvrir deux fois IE, compile en .exe autonome
    // ca ne se voie pas, continuer en appuyent sur F9 ou Run
      vMSIEApp = Variant::GetActiveObject("InternetExplorer.Application");
      }
    catch(...)
      {
       vMSIEApp = Variant::CreateObject("InternetExplorer.Application");
      }
    //Rends l'application IE visible
    vMSIEApp.OlePropertySet("Visible", true);
    vMSIEApp.OleFunction("Navigate", WideString("<a href="http://www.fipradio.fr/player" target="_blank">http://www.fipradio.fr/player</a>"));
    // permet d'attendre le chargement de la page
    while(vMSIEApp.OlePropertyGet("ReadyState") != READYSTATE_COMPLETE);
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Button2Click(TObject *Sender)
    {
    // Fermer IE
    vMSIEApp.OleFunction("Quit");
    // on libere les Variants
    vMSIEApp = Unassigned;
    }
    //---------------------------------------------------------------------------
    Le programme avec une autre fenetre IE ouverte
    Si tu doit gerer la page ce sera plus difficile

  7. #7
    Membre expérimenté
    Homme Profil pro
    Enseignant
    Inscrit en
    Mars 2012
    Messages
    164
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2012
    Messages : 164
    Par défaut
    Ouais bin, ton problème m'aura occupé toute la journée EricNO. Même pas eu le temps de faire la vaiselle, ma femme était pas contente, je lui ai dit "Au moins, je me couche moins niaiseux ce soir".

    Voilà ma solution. Je dis pas qu'elle est la meilleure, c'est celle que j'ai trouvé. Ne jamais confondre "prof" et "professionnel"

    D'abord, j'écrirais un petit module de petites fonctions générales de manipulation de processus. Je les mettrais statique dans une classe, histoire de faire moderne.

    processes.h

    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
     
    // processes.h, guyt54
     
    #ifndef processesH
    #define processesH
     
    #include <windows.h>
    #include <Psapi.h>     // inclure Psapi.lib dans le projet
    #include <classes.hpp>
     
    class TProcesses
    {
      public:
        static bool AppRunning(AnsiString app) ;
        static bool KillByName(AnsiString app) ;
        static void GetAppsRunning(TStrings* names) ;
     
        static AnsiString GetProcessName(int idProcess) ;
      private:
        enum  {MAX_PROCESSES=1000 } ;
    } ;
    #endif
    processes.cpp:

    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
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
     
    // processes.cpp, guyt54
     
    #include "processes.h"
     
    bool TProcesses::AppRunning(AnsiString app)
    // indique si l'application roule
    // app : Nom de l'image du processus (ex: firefox.exe)
    {
       DWORD idProcesses[MAX_PROCESSES] ;
       DWORD id,cnt ;
       bool  found ;
     
       EnumProcesses(idProcesses, MAX_PROCESSES*sizeof(cnt),&cnt) ;
       cnt = cnt / sizeof(cnt) ;   // cnt était en bytes
       found = false ;
       for (DWORD i=0 ; (i < cnt) && !found ; i++)
         {
           id = idProcesses[i] ;
           found =  (GetProcessName(id) == app) ;
         }
       return found ;
    }
     
    bool TProcesses::KillByName(AnsiString app)
    // Tue le processus, ou "app" est le nom de l'image
    {
       DWORD idProcesses[MAX_PROCESSES] ;
       DWORD id,cnt ;
       bool  found,done ;
     
       EnumProcesses(idProcesses, MAX_PROCESSES*sizeof(cnt),&cnt) ;
       cnt = cnt / sizeof(cnt) ;   // cnt était en bytes
       done = false ;
       found = false ;
       for (DWORD i=0 ; (i < cnt) && !found ; i++)
         {
           id = idProcesses[i] ;
           found =  (GetProcessName(id) == app) ;
           if (found)
             {
               HANDLE hProcess ;
               hProcess = OpenProcess(PROCESS_TERMINATE,false,id);
               done = TerminateProcess(hProcess,0);
    		   	     CloseHandle(hProcess);
             }
         }
      return done ;
    }
     
    AnsiString TProcesses::GetProcessName(int idProcess)
    // retourne le nom d'image associé au processus
    {
      AnsiString appName ;
     
      TCHAR name[256] ;
     
      HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
     
                                      FALSE, idProcess );
      name[0] = 0 ;
     
      if (hProcess)
        {
            HMODULE hMod;
            DWORD cbNeeded;
            if ( EnumProcessModules( hProcess, &hMod, sizeof(hMod),
                 &cbNeeded) )
            {
                GetModuleBaseName( hProcess, hMod, name,256) ;
                appName = name ;
            }
        }
      return appName ;
    }
     
     
     void TProcesses::GetAppsRunning(TStrings* names)
     // renvoie dans la liste des noms des processus
     {
       DWORD idProcesses[MAX_PROCESSES] ;
       DWORD cnt ;
       AnsiString name ;
       names->Clear() ;
       EnumProcesses(idProcesses, MAX_PROCESSES*sizeof(cnt),&cnt) ;
       cnt = cnt / sizeof(cnt) ;   // cnt était en bytes
       for (DWORD i= 0 ; i < cnt ; i++)
         {
           name = GetProcessName(idProcesses[i]) ;
           if (!name.IsEmpty()) // il arrive que le nom d'un process soit vide
             names->Add(name) ;
         }
     }
    Je me servirais ensuite de ce module pour te proposer une solution:

    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
     
    #include "processes.h"
     
    AnsiString defaultBrowser = "firefox.exe" ; // variables normalement définis dans TForm1
    bool browserWasOpened ;
     
    void __fastcall TForm1::btLaunchClick(TObject *Sender)
    {
      browserWasOpened = TProcesses::AppRunning(defaultBrowser)  ;
      ShellExecute(NULL, L"open",L"http://guyt54.blogspot.com",NULL, NULL, SW_SHOWNORMAL);
    }
     
    void __fastcall TForm1::btCloseClick(TObject *Sender)
    // ferme le browser ssi il était fermé avant le "Launch"
    {
      if (!browserWasOpened)
         TProcesses::KillByName(defaultBrowser) ;
    }
     
    void __fastcall TForm1::btAppsRunningClick(TObject *Sender)
    // c'est surtout ça qui m'intéressait
    {
      TProcesses::GetAppsRunning(ListBox1->Items)  ;
    }
    ça marche, mais ça ne règle pas tout à fait le problème, il reste à trouver comment on fait pour trouver le browser par défaut.

    Je suis arrivé à ça*, faudrait voir si ça fonctionne dans tous les cas.

    * deuxième version
    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
     
    #include <registry.hpp>
     
    AnsiString GetDefaultOpenApp(AnsiString dot_ext, bool fullPath)
    // retourne l'application associée à "open"
    // dot_ext: inclure le point (ex: ".html)
    // si fullPath, chemin complet, sinon nom de fichier seulement (ex: "firefox.exe")
    {
      TRegistry* reg ;
      AnsiString opener,stg ;
     
      reg = new TRegistry() ;
      reg->RootKey = HKEY_CLASSES_ROOT ;
      if (reg->OpenKeyReadOnly("\\" + dot_ext))
        {
          stg = reg->ReadString("") ; // lire défaut
     
          if (!stg.IsEmpty())
            {
              stg.sprintf("\\%s\\shell\\open\\command",stg) ;
              ShowMessage(stg) ;
              if (reg->OpenKeyReadOnly(stg))
                {
                   opener = reg->ReadString("") ;
                   int pos = opener.Pos("exe") ;
                   if (pos >=0)
                       opener.Delete(opener.Pos("exe")+3,255) ;
                   if (fullPath)
                     {
                       if (opener.Pos("\"")== 1)
                         opener.Delete(1,1)  ;
                     }
                   else
                      opener = ExtractFileName(opener) ;
                }
            }
        }
      delete reg ;
      return opener ;
    }
    Si jamais tu le testes, n'oublie-pas de prendre le lien que j'utilise avec le "ShellExecute", tu vas voir, y a du niveau.

  8. #8
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    22
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 22
    Par défaut
    Merci à tous pour vos réponses,
    je vais prendre le temps d'essayer chacune d'entre elles.

Discussions similaires

  1. [debutant]probleme de recupération de données saisies dans une JDialog
    Par melodie53 dans le forum Agents de placement/Fenêtres
    Réponses: 11
    Dernier message: 07/08/2006, 16h32
  2. [Dates] Probleme de recupération de paramètre ...
    Par acado dans le forum Langage
    Réponses: 4
    Dernier message: 05/04/2006, 10h37
  3. Réponses: 19
    Dernier message: 28/06/2005, 14h16
  4. Réponses: 2
    Dernier message: 14/03/2004, 22h04
  5. TThread: probleme de recuperation du Handle
    Par code34 dans le forum Langage
    Réponses: 8
    Dernier message: 07/09/2003, 03h04

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