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

Bibliothèques C++ Discussion :

Utiliser la fonction CreateProcess()


Sujet :

Bibliothèques C++

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    49
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 49
    Points : 30
    Points
    30
    Par défaut Utiliser la fonction CreateProcess()
    Bonjour,

    J'ai trouvé un super article dans la faq "Gestion des Processus et des Threads". Le seul problème, c'est qu'il n'explique pas les choses toutes simples qu'une débutante comme moi ne maîtrise pas : l'"installation" ...

    Sur d'autres articles trouvés sur le net, j'ai cru comprendre qu'il fallait inclure winbase.h et/ou(?) windows.h. J'ai aussi cru comprendre qu'il y avait des dll à ajouter mais je n'ai pas pu en trouver la liste.

    J'ai recopier le code de "Créer un processus" de la faq dans mon code et celui-ci compile. Pas d'erreur à l'exécution mais seulement la commande CreateProcess() renvoit false, alors qu'en utilisant system(), ça fonctionne très bien.

    A noter que je tiens à utiliser CreateProcess() car j'ai besoin de pouvoir killer le process de l'extérieur.

    Est-ce que quelqu'un pourrait m'expliquer ce qu'il faut inclure pour pouvoir faire marcher la commande ?

    Merci beaucoup

    Madeline

  2. #2
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Bonjour,
    Peux-tu montrer exactement le code que tu as fait ?
    Quel compilateur utilises-tu et sur quel OS?
    Merci

  3. #3
    screetch
    Invité(e)
    Par défaut
    c'est ton jour de chance, je m'en suis servi ce matin =)

    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
    #include <windows.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    int main(int argc, char* argv[])
    {
        char* cmdLine = (char*) malloc(32768);
        const char* target = getenv("GCC_TARGET");
        char* prog = argv[0]+strlen(argv[0])-1;
        int i;
        PROCESS_INFORMATION process;
        STARTUPINFO startup;
        DWORD code;
     
        if(!target)
            target = "mingw32";
     
        while(prog != argv[0] && prog[-1] != '/' && prog[-1] != '\\')
            prog--;
     
        for(i = 1; i < argc; ++i)
        {
            if (strcmp(argv[i], "-b") == 0)
            {
                if(i < argc-1)
                {
                    i++;
                    target=argv[i];
                }
                else
                {
                    fprintf(stderr, "expects argument after -b");
                }
            }
        }
        sprintf(cmdLine, "%s-%s", target, prog);
        for(i = 1; i < argc; ++i)
        {
            if (strcmp(argv[i], "-b") == 0)
            {
                i++;
            }
            else
            {
                strcat(cmdLine, " ");
                strcat(cmdLine, argv[i]);
            }
        }
     
        memset(&startup, 0, sizeof(startup));
        startup.cb = sizeof(startup);
        CreateProcessA(0, cmdLine, 0, 0, TRUE, 0, 0, 0, &startup, &process);
        WaitForSingleObject(process.hProcess, INFINITE);
        GetExitCodeProcess(process.hProcess, &code);
        CloseHandle(process.hThread);
        CloseHandle(process.hProcess);
        free(cmdLine);
        return code;
    }
    compiler ca avec gcc sous windows ou dans visual C++

    ce que le programme fait : il s'appelle gcc.exe, il lance simplement le programme (prefixe)-gcc.exe avec les memes options. il intercepte seulement l'option -b pour changer le préfixe, puis il appelle CreateProcess pour lancer le vrai gcc avec les vrais arguments

    CreateProcess fait partie des fonctions de base, l n'y a donc pas besoin d'inclure autre chose que windows.h (winbase c'est ce que dit la doc de microsoft, cela dit "la fonction est declarée dans winbase.h, pour inclure ce fichier inclure windows.h)
    cela doit se trouver dans la bibliotheque kernel32.lib qui est d'office dans la ligne de commande, donc rien a changer.

    n'hésite pas a poser des questions, je sais pas si je suis clair

  4. #4
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    49
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 49
    Points : 30
    Points
    30
    Par défaut
    Merci pour vos réponses.

    Du coup, mon problème est ailleurs ...

    Je travaille sous Visual studio .NET 2003.

    J'inclus windows.h et winbase.h au début de mon fichier et je mets dans ma fonction exactement le code de la faq qui ressemble au tiens screetch:

    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
     
    	STARTUPINFO         siStartupInfo;
    	PROCESS_INFORMATION piProcessInfo;
     
    	memset(&siStartupInfo, 0, sizeof(siStartupInfo));
    	memset(&piProcessInfo, 0, sizeof(piProcessInfo));
    	siStartupInfo.cb = sizeof(siStartupInfo);
    	if(CreateProcess(NULL, LPWSTR(l_command.toAscii().data()),0,0,FALSE,
    		CREATE_DEFAULT_ERROR_MODE,0,0,                              
    		&siStartupInfo,&piProcessInfo) == FALSE)
    	{
    		return 0;
    	}
    	else
    	{
    		// attente
    		WaitForSingleObject(piProcessInfo.hProcess, INFINITE);
     
    		::CloseHandle(piProcessInfo.hThread);
    		::CloseHandle(piProcessInfo.hProcess);
    		return 1;
    	}
    l_command est un QString qui contient la commande pour lancer mon fichier .bat à exécuter. Les méthodes toAscii() and data() permettent de le convertir en char*.

    A l'exécution pas à pas, le programme ne semble pas rentré dans CreateProcess. C'est pourquoi, j'ai pensé à un problème de dll...

    Cela peut être dû à quoi ?

    Quand j'utilise system, le .bat se lance correctement donc le problème ne peut pas venir de là ...

    Merci pour votre aide

    Madeline

  5. #5
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    LPWSTR(l_command.toAscii().data())
    me semble fortement suspect. (FAQ ici ou ici)

  6. #6
    screetch
    Invité(e)
    Par défaut
    Ne caste pas la chaine en LPWSTR, say mal.
    A la place, appelle la fonction CreateProcessA (A comme Ascii) ou dans les options du projet visual studio, change le flag "Utiliser UNICODE" en "Utiliser MultiByte"(ou quelque chose de similaire)

    Lorsque la fonction echoue, recupère GetÖastError avec ce genre de 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
     
    if(error..)
    {
      const char* msg;
      ::FormatMessageA(
                FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
                0,
                ::GetLastError(),
                MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
                (LPTSTR)&msg,
                0,
                0);
      ::MessageBoxA(0, msg, "error!", MB_ICONERROR|MB_OK);
      ::LocalFree(msg);
    }
    (je le tape de tête donc ca doit pas compiler...)
    Dernière modification par screetch ; 02/04/2009 à 12h29. Motif: ajout du nettoyage...

  7. #7
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    49
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 49
    Points : 30
    Points
    30
    Par défaut
    Je changer la commande


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    CreateProcess(NULL, LPWSTR(l_command.toAscii().data()),0,0,FALSE,
    		CREATE_DEFAULT_ERROR_MODE,0,0,                              
    		&siStartupInfo,&piProcessInfo)
    en :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    CreateProcessA(NULL, l_command.toAscii().data(),0,0,FALSE,
    		CREATE_DEFAULT_ERROR_MODE,0,0,                              
    		&siStartupInfo,&piProcessInfo)
    Assez bizarrement, il ne compile plus et me trouve une erreur sur le 9ème paramètre :

    "error C2664 : 'CreateProcessA' : impossible de convertir le paramètre 9 de 'STARTUPINFO *' en 'LPSTARTUPINFOA'

  8. #8
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Même punition : changer STARTUPINFO en STARTUPINFOA...
    D'une manière général, pour ce genre de méthode/structure. Visual les nomme comme ça :
    BIDULECHOUETTE est la version implicitement vers ton charset courant
    BIDULECHOUETTEW est la version WCHAR
    BIDULECHOUETTEA est la version CHAR

  9. #9
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    49
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 49
    Points : 30
    Points
    30
    Par défaut
    J'ai changé dans mon code l'appel :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    CreateProcess(NULL, LPWSTR(l_command.toAscii().data()),0,0,FALSE,
    		CREATE_DEFAULT_ERROR_MODE,0,0,                              
    		&siStartupInfo,&piProcessInfo)
    en:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    CreateProcessA(NULL, l_command.toAscii().data(),0,0,FALSE,
    		CREATE_DEFAULT_ERROR_MODE,0,0,                              
    		&siStartupInfo,&piProcessInfo)
    J'obtiens maintenant l'erreur suivante à la compilation :

    "
    error C2664: 'CreateProcessA' :impossible de convertir le paramètre 9 de 'STARTUPINFO *' en 'LPSTARTUPINFOA' Les types pointés n'ont aucun rapport entre eux; conversion nécessitant reinterpret_cast, cast de style C ou cast de style fonction
    "

    En effet, avec CreateProcessW, il utilisait un LPSTARTUPINFOW alors que CreateProcessA a besoin d'un LPSTARTUPINFOA. Est ce que je dois vraiment caster la variable comme le dit l'erreur ou y a t il un moyen plus propre ?

    Je préférerais éviter de modifier les propriétés du projet...

    Merci encore de m'aider

    Madeline

  10. #10
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par Madeline Voir le message
    Est ce que je dois vraiment caster la variable comme le dit l'erreur
    Surtout pas. Ce sera le bug assuré.
    Citation Envoyé par Madeline Voir le message
    ou y a t il un moyen plus propre ?
    cf ci-dessus.

  11. #11
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    49
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 49
    Points : 30
    Points
    30
    Par défaut
    Désolé, petit problème de manip, j'avais pas fini mon post et il s'est envoyé sans que je m'en rende compte !

    Merci bien ! Ca compile !

    Cela dit, ça ne fonctionne toujours pas. Je vais essayer de récupérer l'erreur comme me l'a dit screetch...

  12. #12
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    J'ai repris l'exemple de la FAQ et chez moi ça fonctionne parfaitement... Es-tu sûre de la commande fournie (chemin, fichier exe ) ?

  13. #13
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    49
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 49
    Points : 30
    Points
    30
    Par défaut
    L'erreur est

    "Impossible de trouver le fichier "

    Mais de quel fichier parle-t-il?

    Comme je l'ai dit plus haut ma commande est toute simple. Il s'agit de lancer le fichier .bat (qui existe bien).

    Celui-ci contient deux commandes toutes bêtes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    rd /S/Q %1
    mkdir %1
    Je lance ce bat avec un argument un dossier qui existe bien lui aussi ...

    Donc quel fichier peut-il bien chercher et ne pas trouver ?

    L'erreur que je récupère est elle celle retournée par le .bat ? Ou provient-elle de la fonction CreateProcessA() ??

    Pfff, désolé je dois paraître très bête mais je suis un peu perdue !

  14. #14
    screetch
    Invité(e)
    Par défaut
    Tu ne peux pas lancer un fichier .bat comme ca
    il faut lancer
    "cmd.exe /c batfile.bat dir"
    pas "batfile.bat dir"

  15. #15
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    49
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 49
    Points : 30
    Points
    30
    Par défaut
    Merci beaucoup c'était ça le problème en effet !!!

    Merci beaucoup à tous les deux screetch et 3DArchi !

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

Discussions similaires

  1. [ASP] Utiliser la fonction PAD
    Par Hell dans le forum ASP
    Réponses: 4
    Dernier message: 31/03/2005, 16h23
  2. manuel d'utilisation de fonction
    Par SteelBox dans le forum Langages de programmation
    Réponses: 1
    Dernier message: 11/10/2004, 01h28
  3. Utiliser des fonctions Pascal
    Par Neilos dans le forum C++Builder
    Réponses: 2
    Dernier message: 07/03/2004, 15h43
  4. Réponses: 11
    Dernier message: 22/12/2003, 21h06
  5. impossible d'utiliser ma fonction dans un insert
    Par caramel dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 10/04/2003, 15h04

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