begin process at 2012 02 08 22:08:55
  Trouver un code source :
 
dans
 
Accueil > Forum > 

C++ & C++ .NET

 > 

Windows

 > 

System

 > 

CreateProcess et processus infini


Derniers messages déposésPoser une question dans le forum ou lancer une discussion

CreateProcess et processus infini

jeudi 4 juin 2009 à 13:07:49 | CreateProcess et processus infini

Rankin


Salut à tous,

Je suis en train de développer une appli qui lance pas mal de commandes système pour récupérer notamment la configuration du réseau. Pour me simplifier la vie, j'ai écrit une fonction qui exécute une commande et retourne (ou non) le résultat de celle-ci en passant par un pipe. Cette fonction semblait marcher à merveille, mais j'ai un problème à l'exécution de la commande ipconfig /all : d'ordinaire j'attends que le programme que je lance soit terminé avant d'en récupérer le résultat, mais cette commande ne se termine jamais et je la tue au bout de 5 secondes (je remplace le INFINITE par 5000). C'est très laid et j'aimerais donc savoir si il y a quelque chose dans cette fonction qui n'est pas propre comme il faut.
D'autre part, le résultat n'est pas complet : avec 9 interfaces réseau, les deux dernières ne sont pas affichées.

 En voici le code, avec les include et un main, y'a plus qu'à compiler pour tester :


#include <windows.h>
#include <iostream>
#include <string.h>
#include <fstream>

using namespace std;

string commandLine(string command, bool hide, bool encode)
{
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    SECURITY_ATTRIBUTES sa;
    HANDLE hPipeOutput, hPipeInput;
    DWORD dwRead;
    unsigned short size = 4096;
    char buffer[size+1];
    memset(buffer,0,sizeof(buffer));
    string res = "";
    sa.bInheritHandle = TRUE;
    sa.lpSecurityDescriptor = 0;
    sa.nLength = sizeof(SECURITY_ATTRIBUTES);

    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    si.dwFlags = STARTF_USESTDHANDLES;
    //si.wShowWindow = SW_HIDE;
    ZeroMemory(&pi, sizeof(pi));
   
    if(!hide && CreatePipe(&hPipeOutput, &hPipeInput, &sa, 0))   
        si.hStdOutput = hPipeInput;
    else
        //Au cas où la création du pipe ait échoué, on ne lira pas dedans
        hide = true;
    if(CreateProcess(0, (char*)command.c_str(), NULL, NULL, TRUE, CREATE_NO_WINDOW/*|DETACHED_PROCESS*/, NULL, NULL, &si, &pi))
    {
        WaitForSingleObject(pi.hProcess, INFINITE);
        DWORD dwExitCode = 0;
        GetExitCodeProcess(pi.hProcess, &dwExitCode);
        //Si processus toujours présent, on le tue
        if(dwExitCode == STILL_ACTIVE)
        {
            TerminateProcess(pi.hProcess, 0);
        }
        if (!hide)
        {
            bool end = false;
            while (!end)
            {
                if (GetFileSize (hPipeOutput, NULL) >0 && ReadFile(hPipeOutput, buffer, size, &dwRead, NULL))
                {
                    if (encode)
                        CharToOem(buffer,buffer);
                    res += buffer;
                    memset(buffer,0,sizeof(buffer));       
                }
                else
                    end = true;
            }
        }
    }
   
    if(hPipeInput)
        CloseHandle(hPipeInput);

    if(hPipeOutput)
        CloseHandle(hPipeOutput);
    return res;
}


int main()
{
    cout<<commandLine("ipconfig /all",false,true)<<endl;
   return 0;
}


N'hésitez pas à me faire part de vos critiques, même si ce n'est pas de là que vient l'erreur ! C'est toujours bon d'avoir l'avis d'autres personnes pour progresser...
Merci à vous !
jeudi 4 juin 2009 à 20:04:35 | Re : CreateProcess et processus infini

vecchio56

Administrateur CodeS-SourceS
Si tu n'obtiens pas toutes tes interfaces réseau, je suppose que c'est parce que tu tues le thread avant qu'il ne se termine. A ta place je me demanderais plutot pourquoi la commande ipconfig /all ne se termine pas.

_____________________________________
Un éditeur de ressources gratuit pour Windows

jeudi 4 juin 2009 à 20:18:24 | Re : CreateProcess et processus infini

Rankin

C'est effectivement la principale question que je me pose, étant donné que toutes les autres commandes que j'appelle fonctionnent :)
Et a priori non, le résultat tronqué n'est pas dû à la fin d'exécution que je provoque, en allongeant le temps j'ai exactement la même chose. Et si j'exécute la commande à la main dans la console, le résultat est instantané.
jeudi 4 juin 2009 à 20:28:03 | Re : CreateProcess et processus infini

vecchio56

Administrateur CodeS-SourceS
D'accord j'avais compris que la commande bloquait aussi quand tu la lances à la main.
Je ne reproduis pas le problème chez moi...
Tu as identifié à quel endroit ton thread se bloque?

_____________________________________
Un éditeur de ressources gratuit pour Windows

jeudi 4 juin 2009 à 21:30:48 | Re : CreateProcess et processus infini

Rankin

Tu ne reproduis pas le problème, c'est-à-dire que chez toi ce code ne se bloque pas ?
Non je ne sais pas où ça bloque, et à vrai dire je ne sais pas comment faire pour le savoir...


jeudi 4 juin 2009 à 21:39:01 | Re : CreateProcess et processus infini

vecchio56

Administrateur CodeS-SourceS
Oui ca ne se bloque pas chez moi.
Pour savoir ou ca bloque, tu utilises un debugger ou tu utilise un système de trace (comme l'écriture dans un fichier par exemple), ce qui te permettra de voir ou ca bloque. A priori c'est sans doute le ReadFile.

_____________________________________
Un éditeur de ressources gratuit pour Windows

jeudi 4 juin 2009 à 21:50:03 | Re : CreateProcess et processus infini

Rankin

Bon c'est déjà un point positif si ça ne bloque pas chez toi ; par contre c'est la commande ipconfig qui ne se termine pas, c'est le wait qui est bloquant ; je passe outre en mettant 5000ms d'attente au lieu d'INFINITE. Sinon, quand je fais Ctrl+C pour stopper le programme, j'ai toujours un ipconfig.exe qui tourne dans le gestionnaire des tâches.
C'est vraiment étrange, quelle est la différence entre l'appel de la commande par CreateProcess et son appel à la main ?


vendredi 12 juin 2009 à 14:47:36 | Re : CreateProcess et processus infini

Rankin

Désolé de remonter le topic mais finalement j'ai encore eu le même problème sur une autre machine et avec Vista (la première est sous XP).
En commentant certaines lignes, j'ai pu voir que si je ne créais pas de tube, la commande était instantanée : j'ai même testé de rediriger la sortie vers un fichier pour m'assurer qu'elle avait fonctionné correctement.
Etant donné que je ne bloque pas sur le ReadFile (ce dont je suis sûr aussi : le processus ne se termine pas même si le Read est commenté à partir du moment où j'ai défini le flux de sortie de la commande vers l'entrée du tube).
Aucune idée sur ce qui pourrait aller de travers ? (le code n'a pas changé par rapport au premier post).

Merci !


vendredi 12 juin 2009 à 15:59:34 | Re : CreateProcess et processus infini

Rankin

Bon, j'ai finalement trouvé l'erreur : je créais le processus et attendais sa fin ou le détruisais au bout de 5 secondes. Mais en redirigeant la sortie standard du processus vers l'entrée de mon tube, je créais dans certains cas une situation d'interblocage.
Pour la plupart des commandes, pas de problème. En revanche, pour un ipconfig /all qui représente pas mal de lignes sur les deux machines où j'ai testé mon programme (et c'est pour ça que chez toi ça a marché sans souci vecchio56), le processus écrit dans le tube jusqu'au moment où il est plein : il attend donc que quelqu'un lise à l'autre bout.
Le problème, c'est que mon programme ne lisait qu'une fois le processus fini : situation inextricable.

J'ai donc changé un peu tout ça en faisant confiance au processus (si il ne se finit pas, ma boucle non plus, mais bon, pour un ipconfig... devrait pas y avoir trop de risques). Je poste ma fonction modifiée, des fois que ça intéresse quelqu'un (je déteste les topics pas finis ou pire, quand le mec dit "j'ai trouvé" sans donner plus d'explications).

string commandLine(string command, bool hide, bool encode)
{
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    SECURITY_ATTRIBUTES sa;
    HANDLE hPipeOutput, hPipeInput;
    DWORD dwRead;
    unsigned short size = 1024;
    char buffer[size+1];
    memset(buffer,0,sizeof(buffer));
    string res = "";
    sa.bInheritHandle = TRUE;
    sa.lpSecurityDescriptor = 0;
    sa.nLength = sizeof(SECURITY_ATTRIBUTES);

    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    si.dwFlags = STARTF_USESTDHANDLES;
    //si.wShowWindow = SW_HIDE;
    ZeroMemory(&pi, sizeof(pi));
  
   if(!hide && CreatePipe(&hPipeOutput, &hPipeInput, &sa, 0))  
        si.hStdOutput = hPipeInput;
    else
        //Au cas où la création du pipe ait échoué, on ne lira pas dedans
        hide = true;
    if(CreateProcess(0, (char*)command.c_str(), NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi))
    {
        DWORD dwExitCode = 0;
        if(hide)
        {
            WaitForSingleObject(pi.hProcess, 5000);
            GetExitCodeProcess(pi.hProcess, &dwExitCode);
            //Si processus toujours présent, on le tue
            if(dwExitCode == STILL_ACTIVE)
            {
                TerminateProcess(pi.hProcess, 0);
            }
        }
        else
        {
            int left = GetFileSize (hPipeOutput, NULL);
            GetExitCodeProcess(pi.hProcess, &dwExitCode);
            while(dwExitCode == STILL_ACTIVE || left > 0)
            {
                ReadFile(hPipeOutput, buffer, size, &dwRead, NULL);
                cout<<dwRead<<endl;
                if (encode)
                    CharToOem(buffer,buffer);
                res += buffer;
                memset(buffer,0,sizeof(buffer));
                left = GetFileSize (hPipeOutput, NULL);
                GetExitCodeProcess(pi.hProcess, &dwExitCode);
            }
        }
    }
    if(hPipeInput)
        CloseHandle(hPipeInput);

    if(hPipeOutput)
        CloseHandle(hPipeOutput);
    return res;
}

Je vérifie dans ma boucle du ReadFile à la fois qu'il reste des choses à lire grâce à GetFileSize, mais aussi si le processus est toujours actif : tant qu'il n'est pas terminé il peut toujours avoir quelque chose à dire (et surtout, le premier read intervient avant la fin de l'exécution de l'ipconfig chez moi).

Dernière interrogation : après le ReadFile, il y a un cout. Si je ne le mets pas, le programme ne se finit pas. La boucle n'est pas infinie, il se bloque dans la boucle. Je ne sais pas où, parce que si je fais un affichage ça se termine. Si j'affiche par exemple "toto", ça ne marche pas. Vraisemblablement, il faut que j'affiche le contenu d'une de mes variables. Et si je place le cout ailleurs, soit ça ne marche pas sous XP, soit ça ne marche pas sous Vista. Cet emplacement semble être le seul possible pour que le programme se finisse sur les deux systèmes. J'avoue que là, je comprends pas trop d'où ça vient... (ça marche aussi avec cerr)

Je suis preneur pour toute idée :)


Cette discussion est classée dans : buffer, sizeof, pi, if, hpipeoutput


Répondre à ce message

Sujets en rapport avec ce message

Pipes sous windows [ par ssmint ] Bonjour à tous, Voilà je voudrais piloter CMD.EXE gràce à mon prog pour au final pouvoir réaliser une sorte de telnet...J'ai redirigé l'entrée et la s Socket en C [ par RM50Man ] WSADATA ws;                    WSAStartup(MAKEWORD(2,0), &ws);              &n Redirection sortie [ par M5i9k ] Bonjour à tous,je voudrais lire la sortie d'une console lancée à partir de mon programme (j'utilise CreateProcess), je voudrais savoir si je suis sur icones bureau [ par sam20 ] Bonjour .Avec ce code j'ai la liste des icones du bureauvoid GetIcon(){ // récupération plateforme d'exécution OSVERSIONINFO osvi; osvi.dwOSVersionInf urgent [ par sendouda ] j'ai voulu exécuter une commande dos en MFC sans qu'on m'ouvre la fenêtre dos.j'ai utilisé le code suivant avec cmd ets une Cstring qui contient la co probleme avec une boucle do while [ par miki42 ] Bonjour a tous,voila je realise un logiciel de brute force ftp ceci etant pour améliorer mon niveau en programation,bref j'ai un probleme sur ma boucl Probleme fonction creta process [ par morgandetoi06 ] bonjour, je suis en train de faire un installeur de patch correctifs winXPmais je n arrive pas à lancer mes patch en leur passant les parametres "-q - client serveur echange de donne [ par bapdur ] voici la version dun client et dun serveur que je fais pour un jeu mais les donnes son envoyer en continu jaimerais aire en sorte que si je tape un ca Récupération "au fil de l'eau" du résulat d'une commande DOS [ par 10MilleSabords ] Bonjour,Tout est dans le sujet. Est-ce possible?Voici ou j'en suis:Je lance ma ligne de commande par un CreateProcess puis je récupère le résulat dans Sockets [ par Suxyt ] Bonjour à tous, Actuellement, je travaille sur un projet qui consiste d'envoyer et de recevoir des données en construisant l'en-tête soi-même. Pour e


Nos sponsors


Sondage...

Comparez les prix

CalendriCode

Février 2012
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
272829    

Consulter la suite du CalendriCode

Photothèque

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,686 sec (4)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales