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++ Discussion :

Commande DOS sans affichage de la fenêtre mais en récupérant le résultat


Sujet :

C++

  1. #1
    Membre du Club
    Inscrit en
    Septembre 2003
    Messages
    101
    Détails du profil
    Informations forums :
    Inscription : Septembre 2003
    Messages : 101
    Points : 57
    Points
    57
    Par défaut Commande DOS sans affichage de la fenêtre mais en récupérant le résultat


    Pour des besoins spécifiques, je fais une IHM en C++ Builder 6 pour utiliser NeroCmd.exe, exécutable fournit avec Nero qui permet de graver des CD en ligne de commande.

    J'utilise NeroCmd pour récupérer les caractéristiques du graveur, du CD... Il faut donc que je récupère la sortie console pour la parser et récupérer ce qui m'intéresse.

    J'avais d'abord fait un "system(commande_nero);", commande_nero s'occupant également de rediriger la sortie vers un fichier temp ("nerocmd arg > fichier.tmp") que je parsais avant de l'effacer. Ca marche mais :
    - c'est pas propre
    - ça utilise un fichier temp
    - ça affiche une fenêtre DOS pendant 0,2s

    J'ai essayé ShellExecute qui permet de masquer la fenêtre (SW_HIDE) mais impossible de récupérer le résultat, du moins dans mes essais.

    Et puis je suis tombé sur un code utilisant CreateProcess, qui récupère la sortie standard directement dans un handle. Ca fonctionne, mais j'ai toujours la fenêtre qui s'affiche. Ca utilise un STARTUPINFO, mais si je le paramètre pour cacher la fenêtre (dwFlags=STARTF_USESHOWWINDOW et wShowWindow=SW_HIDE) ça ne me récupère plus la sortie standard.

    Ma question est : y'a t-il moyen de combiner les 2, masquer la fenêtre DOS et récupérer la sortie console, si possible sans passer par une redirection et un fichier temporaire ?

    Merci !

    Pour info, le résultat retourné par NeroCmd peut avoir la tête là :
    Drv: Adapter Underrun Protection Technology # type ID
    -------------------------------------------------------------------------------
    d TSSTcorp CD-ROM TS-H192C <none> 0 atapi 0
    e _NEC DVD+-RW ND-3530A JustLink 0 atapi 1
    f YO9204R SOU432M <none> 2 dtscsi 0
    ? Image Recorder <none> -1 Virtual 0

    Ok.
    Ci-dessous le code que j'ai récupéré et un peu modifié. Le résultat de la commande lancée est sensé se trouver dans strRes.

    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
     
    void TParseFile::ExecuteCommand(AnsiString strCmd)
    {
      const int BUFSIZE = 256;
      AnsiString strRes, procstdout = "", procstderr = "";
      char *CommandLine;
      unsigned long dwExitCode;
      CHAR chBuf[BUFSIZE];
      DWORD dwRead;
      STARTUPINFO siStartupInfo;
      PROCESS_INFORMATION piProcessInfo;
      HANDLE PipeInputRead, PipeInputWrite, PipeOutputRead, PipeOutputWrite;
     
      SECURITY_ATTRIBUTES securityattribs = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
      ZeroMemory(&siStartupInfo, sizeof(siStartupInfo));
     
      CreatePipe(&PipeOutputRead, &PipeOutputWrite, &securityattribs, 0);
      CreatePipe(&PipeInputRead, &PipeInputWrite, &securityattribs, 0);
     
      siStartupInfo.cb = sizeof(siStartupInfo);
     
      // Redirection vers un fichier temp désactivée
      //strCmd = strCmd + " > " + ResultTempFile;
      CommandLine = strCmd.c_str();
     
      // Masquer la fenêtre, mais ne récupére par le résultat
      /*
      siStartupInfo.dwFlags = STARTF_USESHOWWINDOW;
      siStartupInfo.hStdInput = PipeInputRead;
      siStartupInfo.hStdOutput = PipeOutputWrite;
      siStartupInfo.hStdError = PipeOutputWrite;
      siStartupInfo.wShowWindow = SW_HIDE;
      */
     
      // Afficher la fenêtre et récupérer le résultat
      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);
        WaitForSingleObject(piProcessInfo.hProcess, INFINITE);
        GetExitCodeProcess(piProcessInfo.hProcess, &dwExitCode);
        if (dwExitCode != STILL_ACTIVE)
          CloseHandle(piProcessInfo.hProcess); // fermer le handle de process
     
        CloseHandle(PipeOutputWrite);
        CloseHandle(PipeInputRead);
        CloseHandle(PipeInputWrite);
     
        while (ReadFile(PipeOutputRead, chBuf, BUFSIZE-1, &dwRead, NULL) && (dwRead != 0))
        {
          chBuf[dwRead] = '\0';
          procstdout += chBuf;
          strRes = chBuf;
        }
     
        while (ReadFile(PipeOutputRead, chBuf, BUFSIZE-1, &dwRead, NULL) && (dwRead != 0))
        {
          chBuf[dwRead] = '\0';
          procstderr += chBuf;
        }
        CloseHandle(PipeOutputRead);
      }
      else
      {
        MessageBox(NULL, CommandLine, "Command Line Error", MB_OK|MB_ICONSTOP);
        CloseHandle(PipeOutputWrite);
        CloseHandle(PipeInputRead);
      }
    }

  2. #2
    Membre averti Avatar de uriotcea
    Homme Profil pro
    Ingénieur / physicien
    Inscrit en
    Septembre 2003
    Messages
    1 301
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur / physicien
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2003
    Messages : 1 301
    Points : 444
    Points
    444
    Par défaut
    salut,

    ca vaut ce que ca vaut, mais avec CreateProcess tu peux lui indiquer la position ou la taille de la fenetre, il me semble en tous cas. Alors en mettant la taille à zero ou la position en dehors de l'ecran, tu peux peu-etre t'en sortir, même si je te l'accorde c'est pas trés satisfaisant.
    Je m'etonne tout de même qu'avec l'option !HIDE tu ne puisses plus rediriger la sortie standard vers un fichier.

  3. #3
    Membre averti Avatar de uriotcea
    Homme Profil pro
    Ingénieur / physicien
    Inscrit en
    Septembre 2003
    Messages
    1 301
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur / physicien
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2003
    Messages : 1 301
    Points : 444
    Points
    444
    Par défaut
    Une autre idée qui me vient, as-tu essayé la fonction:
    WinExec("...",HIDE);

  4. #4
    Membre du Club
    Inscrit en
    Septembre 2003
    Messages
    101
    Détails du profil
    Informations forums :
    Inscription : Septembre 2003
    Messages : 101
    Points : 57
    Points
    57
    Par défaut
    Merci pour les réponses ! Mais ça ne résoudra pas mon problème : la seule façon de récupérer la sortie console est d'avoir le dwFlags de startupinfo à STARTF_USESTDHANDLES, or pour masquer la fenêtre il faut STARTF_USESHOWWINDOW et pour spécifier taille et position, STARTF_USEPOSITION ou STARTF_USESIZE. Bref, c'est juste incompatible... A moins de repasser par la solution du fichier temporaire, si toutefois la redirection vers un fichier fonctionne, ce qui n'avait pas l'air d'être le cas dans mes tests précédents.

    Quant à WinExec, je vais regarder, mais c'est plutôt reservé à une rétrocompatibilité pour des anciennes versions de Windows.

  5. #5
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 379
    Points : 41 573
    Points
    41 573
    Par défaut
    Huh ? Pourquoi incompatible ?

  6. #6
    Membre du Club
    Inscrit en
    Septembre 2003
    Messages
    101
    Détails du profil
    Informations forums :
    Inscription : Septembre 2003
    Messages : 101
    Points : 57
    Points
    57
    Par défaut
    Ben d'après l'aide Borland, c'est soit STARTF_USESTDHANDLES avec possibilité de récupérer la sortie, soit STARTF_USESHOWWINDOW avec possibilité de masquer la fenêtre. Mais pas les deux

  7. #7
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 379
    Points : 41 573
    Points
    41 573
    Par défaut
    Ah oui, j'avais mal lu.
    Ben, il faut dire que STARTF_USESHOWWINDOW, c'est pour les programmes fenêtrés (même si la DOC MICROSOFT OFFICIELLE ne dit pas que c'est vraiment incompatible, surtout sachant qu'un programme console PEUT ouvrir une fenêtre).

    Pour masquer la console, il faut directement passer le flag CREATE_NO_WINDOW ou DETACHED_PROCESS à CreateProcess().

  8. #8
    Membre du Club
    Inscrit en
    Septembre 2003
    Messages
    101
    Détails du profil
    Informations forums :
    Inscription : Septembre 2003
    Messages : 101
    Points : 57
    Points
    57
    Par défaut
    Ouh pinaise ça marche avec CREATE_NO_WINDOW. Tout simplement !

    Merci !

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

Discussions similaires

  1. Exécuter un EXE DOS sans ouvrir de fenêtre de commande
    Par Pierre GIRARD dans le forum Débuter
    Réponses: 13
    Dernier message: 11/02/2014, 20h59
  2. [AC-2007] Traitement de commandes DOS sans externaliser de fichier
    Par SweloMyli dans le forum VBA Access
    Réponses: 2
    Dernier message: 29/10/2011, 16h58
  3. Lancer une commande dos sans voir la fenêtre
    Par Nicopelo dans le forum Windows
    Réponses: 2
    Dernier message: 07/06/2007, 09h12
  4. Affichage d'une fenêtre sans la barre d'outil
    Par itrione dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 20/06/2006, 23h43
  5. [Dos] Lancer une commande dos sans attendre la fin
    Par MrEddy dans le forum Windows
    Réponses: 4
    Dernier message: 09/06/2005, 17h38

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