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 :

Récupérer le retour d'une commande MS-DOS dans une variable sous C++ Builder XE2 [Langage/Algorithme]


Sujet :

C++Builder

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Février 2007
    Messages
    164
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 164
    Points : 85
    Points
    85
    Par défaut Récupérer le retour d'une commande MS-DOS dans une variable sous C++ Builder XE2
    Bonjour,

    J'aimerais exécuter et récupérer le retour d'une commande MS-DOS sous C++ Builder XE2. Je n'ai pas trouvé beaucoup d'informations concernant ce sujet sur le forum, c'est pourquoi je poste ce message.

    J'ai le code suivant :

    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
    wchar_t* __fastcall TForm5::RunDOScmd(wchar_t* CommandLine)
    {
        STARTUPINFO siStartupInfo;
        PROCESS_INFORMATION piProcessInfo;
        unsigned long dwExitCode;
     
        HANDLE PipeInputRead;
        HANDLE PipeInputWrite;
        HANDLE PipeOutputRead;
        HANDLE PipeOutputWrite;
     
        SECURITY_ATTRIBUTES securityattribs =
        {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
     
        ZeroMemory(&siStartupInfo, sizeof(siStartupInfo));
        // initialisation de la taille
        siStartupInfo.cb = sizeof(siStartupInfo);
     
        // Create pipe for standard output redirection
        CreatePipe(&PipeOutputRead, &PipeOutputWrite, &securityattribs, 0);
        // Create pipe for standard input redirection.
        CreatePipe(&PipeInputRead, &PipeInputWrite, &securityattribs, 0);
     
        siStartupInfo.dwFlags = STARTF_USESTDHANDLES;
        siStartupInfo.hStdInput = PipeInputRead;
        siStartupInfo.hStdOutput = PipeOutputWrite;
        siStartupInfo.hStdError = PipeOutputWrite;
     
        bool pSuccess = CreateProcess(NULL, CommandLine, NULL, NULL, true, 0, NULL, NULL, &siStartupInfo, &piProcessInfo);
     
        if (pSuccess)
        {
            CloseHandle(piProcessInfo.hThread); // fermer le handle de thread dès qu'il devient inutile
            WaitForSingleObject(piProcessInfo.hProcess, INFINITE);
            GetExitCodeProcess(piProcessInfo.hProcess, &dwExitCode);
            if (dwExitCode != STILL_ACTIVE)
                CloseHandle(piProcessInfo.hProcess); // fermer le handle de process
        }
        else
        {
            CloseHandle(PipeOutputWrite);
            CloseHandle(PipeInputRead);
            return (L"perdu");
        }
     
        CloseHandle(PipeOutputWrite);
        CloseHandle(PipeInputRead);
        CloseHandle(PipeInputWrite);
     
        // Read output from the child process.
        DWORD dwRead;
        CHAR chBuf[4096];
        String procstdout = "", procstderr = "";
     
        while (ReadFile(PipeOutputRead, chBuf, 4095, &dwRead, NULL) && (dwRead != 0))
        {
            chBuf[dwRead] = '\0';
            procstdout += chBuf;
            Edit2->Text = chBuf;
        }
     
        while (ReadFile(PipeOutputRead, chBuf, 4095, &dwRead, NULL) && (dwRead != 0))
        {
            chBuf[dwRead] = '\0';
            procstderr += chBuf;
        }
        CloseHandle(PipeOutputRead);
    }
    Par contre, la commande "CreateProcess(NULL, CommandLine, NULL, NULL, true, 0, NULL, NULL, &siStartupInfo, &piProcessInfo);" me renvoie toujours faux ...

    Merci beaucoup pour votre aide si vous avez des idées,

  2. #2
    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
    Points : 3 766
    Points
    3 766
    Par défaut
    Salut Mercusyo
    Un lien sur l'execution d'une commande MSDOS
    Ce n'est pas tout a fait ce que tu cherche mais cela peut etre une piste
    --
    Plutot que d'essayer de réinventer la roue, apprenons à nous en servir

  3. #3
    Membre averti
    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
    Points : 356
    Points
    356
    Par défaut
    Salut,

    Ma petite expérience avec ce genre de fonctions.

    Pour exécuter une commande de type DOS, j'ai utilisé pendant des années la fonction "WinExec". Puis je suis tombé là-dessus (dans MSDN):

    Note This function (WinExec)is provided only for compatibility with 16-bit Windows. Applications should use the CreateProcess function.

    Alors j'ai suivi leur conseil et j'ai fini par trouver comme faire (ciel que je déteste quand c'est compliqué)

    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
     
    oid TGenTools::ExecuteProcess(AnsiString applicationName,
                                   AnsiString commandLine,
                                   AnsiString startDir,
                                   bool showWindow, bool modalWindow)
     // http://www.tek-tips.com/faqs.cfm?fid=1954
     // ApplicationName: Nom de l'Application. Peut être vide, alors la commandLine
     //                  doit contenir le nom de l'application
     // commandLine: ligne de commande
     
     {
      int res ;
      char* cmd ;
      char* dir ;
      STARTUPINFO StartInfo; // name structure
      PROCESS_INFORMATION ProcInfo; // name structure
     
     
      if (!applicationName.IsEmpty())
        commandLine = applicationName + " " + commandLine ;
      cmd = StgToCharPtr(commandLine) ;  // NULL si vide
      dir = StgToCharPtr(startDir) ;
      memset(&ProcInfo, 0, sizeof(ProcInfo)); // Set up memory block
      memset(&StartInfo, 0 , sizeof(StartInfo)); // Set up memory block
      StartInfo.cb = sizeof(StartInfo); // Set structure size
      StartInfo.dwFlags = STARTF_USESHOWWINDOW ;  // Necessary for wShowWindow to work
      if (showWindow)
         StartInfo.wShowWindow = SW_SHOW; // Hide window
      else
         StartInfo.wShowWindow = SW_HIDE; // Hide window
     
      res = CreateProcess(NULL, cmd, NULL, NULL, NULL, NULL, NULL,
                          dir,
                          &StartInfo, &ProcInfo);
      if (res && modalWindow)
       WaitForSingleObject(ProcInfo.hThread, INFINITE); // wait forever for process to finish
    }
    Ça fonctionnait jusqu'à je tombe en Window 7. Puis, je suis tombé sur la fonction ShellExecute qui fonctionne à merveille, au delà de mes espérances même. Peut-être qu'elle ferait l'affaire dans ton cas***.

    http://msdn.microsoft.com/en-us/libr...=vs.85%29.aspx

    Tiens j'en profite pour vous refiler un petit truc juste au cas où...

    Dans votre boite de dialogue "à propos..." , vous avec un label (lbLink) qui contient le lien de votre site. Voici le code qui va lancer le browser par défaut avec le lien passé en paramètre:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    #include <windows.h>
    void __fastcall TfrmAbout::lbLinkClick(TObject *Sender)
    {
    ShellExecute(NULL, L"open",lbLink->Caption.c_str(),NULL, NULL, SW_SHOWNORMAL);
    }
    *** J'en doute, après avoir bien relu ton post

  4. #4
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    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 : 13 459
    Points : 24 873
    Points
    24 873
    Par défaut
    Si tu utilises PipeOutputWrite comme Pipe pour hStdOutput et hStdError, tu ne pourras pas faire la différence entre les deux et seul la 1ere boucle de ReadFile fonctionnera

    regarde la MSDN How to spawn console processes with redirected standard handles \ Comment appeler un processus console avec une redirection des canaux standards.


    J'ai fait ceci en Delphi, tout doit se jouer sur les différents NULL que tu passe, j'ai utilisé ce code pour lancer PHP.exe et d'autres programmes consoles comme ceux de DCMTK

    tu as préparé un siStartupInfo mais tu ne l'utilises pas ?
    le chemin est-il exacte ?

    Tu es bien en mappage wchar_t, as-tu testé CreateProcessW
    un projet BCB6 ou 2007 migré en 2009 à XE2 reste Ansi !

    piProcessInfo, moi, je lui ai fait un ZeroMemory, mais comme c'est out ça devrait pas poser problème

    on a eu un sujet proche récemment Créer un GUI pour une application console compilée
    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

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Février 2007
    Messages
    164
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 164
    Points : 85
    Points
    85
    Par défaut
    Merci beaucoup pour vos réponses ,

    J'ai avancé de mon côté également, mon code ci-dessous fonctionne correctement :

    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
    char* __fastcall TForm5::RunDOScmd(wchar_t* CommandLine)
    {
    	STARTUPINFO siStartupInfo;
    	PROCESS_INFORMATION piProcessInfo;
    	unsigned long dwExitCode;
     
    	HANDLE PipeInputRead;
    	HANDLE PipeInputWrite;
    	HANDLE PipeOutputRead;
    	HANDLE PipeOutputWrite;
     
    	SECURITY_ATTRIBUTES securityattribs = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
     
    	ZeroMemory(&siStartupInfo, sizeof(siStartupInfo));
    	// initialisation de la taille
    	siStartupInfo.cb = sizeof(siStartupInfo);
     
    	// Create pipe for standard output redirection
    	CreatePipe(&PipeOutputRead, &PipeOutputWrite, &securityattribs, 0);
    	// Create pipe for standard input redirection.
    	CreatePipe(&PipeInputRead, &PipeInputWrite, &securityattribs, 0);
     
    	siStartupInfo.dwFlags = STARTF_USESTDHANDLES;
    	siStartupInfo.wShowWindow = SW_HIDE;
    	siStartupInfo.hStdInput = PipeInputRead;
    	siStartupInfo.hStdOutput = PipeOutputWrite;
     
    	bool pSuccess = CreateProcess(NULL, CommandLine, NULL, NULL, true, 0, NULL, NULL, &siStartupInfo, &piProcessInfo);
     
    	if (pSuccess)
    	{
    		CloseHandle(piProcessInfo.hThread); // fermer le handle de thread dès qu'il devient inutile
    		WaitForSingleObject(piProcessInfo.hProcess, INFINITE);
    		GetExitCodeProcess(piProcessInfo.hProcess, &dwExitCode);
    		if (dwExitCode != STILL_ACTIVE)
    			CloseHandle(piProcessInfo.hProcess); // fermer le handle de process
    	}
    	else
    	{
    		CloseHandle(PipeOutputWrite);
    		CloseHandle(PipeInputRead);
    		return "";
    	}
     
    	CloseHandle(PipeOutputWrite);
    	CloseHandle(PipeInputRead);
    	CloseHandle(PipeInputWrite);
     
    	// Read output from the child process.
    	DWORD dwRead;
    	CHAR chBuf[SIZEBUF];
     
    	bool isReadFile = ReadFile(PipeOutputRead, chBuf, SIZEBUF-1, &dwRead, NULL);
     
    	CloseHandle(PipeOutputRead);
    	return chBuf;
    }
    Seul petit bémol, j'ai toujours une fenêtre MS-DOS qui apparaît, même avec la commande
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    siStartupInfo.wShowWindow = SW_HIDE;
    Pour info, c'est pour appeler une commande de DCMTK (dcmftest.exe)

    J'ai également essayé avec le premier paramètre "lpApplicationName" de la méthode "CreateProcess", mais là, plus rien ne fonctionne ... j'envoie pour
    "lpApplicationName = dcmftest" et pour "lpCommandLine = D:\\1.dcm"

    Comment faire pour rendre invisible cette fenêtre en espérant que ce soit possible ...

    Merci,

  6. #6
    Membre régulier
    Profil pro
    Inscrit en
    Février 2007
    Messages
    164
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 164
    Points : 85
    Points
    85
    Par défaut
    Je viens de trouver la réponse seul en regardant MSDN, voici donc le code en mappage wchar_t :


    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
    char* __fastcall TForm5::RunDOScmd(wchar_t* CommandLine)
    {
    	STARTUPINFO siStartupInfo;
    	PROCESS_INFORMATION piProcessInfo;
    	unsigned long dwExitCode;
     
    	HANDLE PipeInputRead;
    	HANDLE PipeInputWrite;
    	HANDLE PipeOutputRead;
    	HANDLE PipeOutputWrite;
     
    	SECURITY_ATTRIBUTES securityattribs = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
     
    	ZeroMemory(&siStartupInfo, sizeof(siStartupInfo));
    	// initialisation de la taille
    	siStartupInfo.cb = sizeof(siStartupInfo);
     
    	// Create pipe for standard output redirection
    	CreatePipe(&PipeOutputRead, &PipeOutputWrite, &securityattribs, 0);
    	// Create pipe for standard input redirection.
    	CreatePipe(&PipeInputRead, &PipeInputWrite, &securityattribs, 0);
     
    	siStartupInfo.dwFlags = STARTF_USESTDHANDLES;
    	siStartupInfo.hStdInput = PipeInputRead;
    	siStartupInfo.hStdOutput = PipeOutputWrite;
     
    	bool pSuccess = CreateProcess(NULL, CommandLine, NULL, NULL, true, CREATE_NO_WINDOW, NULL, NULL, &siStartupInfo, &piProcessInfo);
     
    	if (pSuccess)
    	{
    		CloseHandle(piProcessInfo.hThread); // fermer le handle de thread dès qu'il devient inutile
    		WaitForSingleObject(piProcessInfo.hProcess, INFINITE);
    		GetExitCodeProcess(piProcessInfo.hProcess, &dwExitCode);
    		if (dwExitCode != STILL_ACTIVE)
    			CloseHandle(piProcessInfo.hProcess); // fermer le handle de process
    	}
    	else
    	{
    		CloseHandle(PipeOutputWrite);
    		CloseHandle(PipeInputRead);
    		return "";
    	}
     
    	CloseHandle(PipeOutputWrite);
    	CloseHandle(PipeInputRead);
    	CloseHandle(PipeInputWrite);
     
    	// Read output from the child process.
    	DWORD dwRead;
    	CHAR chBuf[SIZEBUF];
     
    	bool isReadFile = ReadFile(PipeOutputRead, chBuf, SIZEBUF-1, &dwRead, NULL);
     
    	CloseHandle(PipeOutputRead);
    	return chBuf;
    }
    J'ai modifié la ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     bool pSuccess = CreateProcess(NULL, CommandLine, NULL, NULL, true, CREATE_NO_WINDOW, NULL, NULL, &siStartupInfo, &piProcessInfo);
    au lieu de mettre 0 à "dwCreationFlags" j'ai précisé "CREATE_NO_WINDOW" et en supprimant l'instruction
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    siStartupInfo.wShowWindow = SW_HIDE;
    Voilou, si cela peut aider et merci !

  7. #7
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    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 : 13 459
    Points : 24 873
    Points
    24 873
    Par défaut
    En fait pour que wShowWindow soit pris en compte, il faut mettre STARTF_USESHOWWINDOW

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    StartupInfo.dwFlags := STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; // Active wShowWindow et hStdOutput/hStdError
    StartupInfo.wShowWindow := SW_HIDE;
    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

  8. #8
    Membre régulier
    Profil pro
    Inscrit en
    Février 2007
    Messages
    164
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 164
    Points : 85
    Points
    85
    Par défaut
    Merci pour le complément d'informations ShaiLeTroll

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

Discussions similaires

  1. [Débutant] Variable dans une commande MS-DOS en vb.net
    Par Barbe-Bleu dans le forum VB.NET
    Réponses: 2
    Dernier message: 18/11/2012, 15h17
  2. [XL-2010] Intégrer une commande SQL (complexe) dans une macro
    Par urbandot dans le forum Macros et VBA Excel
    Réponses: 0
    Dernier message: 14/11/2011, 10h50
  3. Réponses: 8
    Dernier message: 25/09/2008, 20h22
  4. executer une commande clé contenue dans une cellule
    Par herji dans le forum Macros et VBA Excel
    Réponses: 5
    Dernier message: 08/09/2008, 17h12
  5. [MySQL] executer une commande php contenu dans une variable
    Par Stopher dans le forum PHP & Base de données
    Réponses: 4
    Dernier message: 23/11/2006, 15h44

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