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

Langage Delphi Discussion :

[D2010] Comment utiliser CreateProcess pour exécuter une commande DOS ?


Sujet :

Langage Delphi

  1. #1
    Expert éminent
    Avatar de Lung
    Profil pro
    Analyste-programmeur
    Inscrit en
    Mai 2002
    Messages
    2 674
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste-programmeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 2 674
    Points : 7 063
    Points
    7 063
    Par défaut [D2010] Comment utiliser CreateProcess pour exécuter une commande DOS ?
    Sous Delphi 2010, comment utiliser CreateProcess pour exécuter une commande DOS ?

    Voici le code qui fonctionne sous Delphi 6 :
    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
    procedure TForm1.GetConsoleText(const szCommande: String; var szResult: String);
    const
       LENBUFF = 512;  
    var
       hReadPipe, hWritePipe: THandle;
       sa: TSecurityAttributes;
       si: TStartupInfo;
       pi: TProcessInformation;
       lpBuffer: Array[0..LENBUFF] of char;
       nBytesRead: Cardinal;
       nBytesToRead: Integer;
    begin
       sa.nLength := Sizeof(sa);
       sa.lpSecurityDescriptor := nil;
       sa.bInheritHandle := True;
     
       if not CreatePipe(hReadPipe, hWritePipe, @sa, 0) then
       begin
          Application.MessageBox(PChar('Erreur :  la création du pipe a échoué !' + #13#10 + SysErrorMessage(GetLastError)), PChar(Caption + ' - erreur'), MB_ICONERROR + MB_OK);
          Exit;
       end;
     
       FillChar(si, Sizeof(si), 0);
       si.cb := Sizeof(si);
       si.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
       si.wShowWindow := SW_HIDE;
       si.hStdInput := 0;
       si.hStdOutput := hWritePipe;
       si.hStdError := hWritePipe;
     
       if not CreateProcess(nil, PChar(szCommande), nil, nil, True, 0, nil, nil, si, pi) then
       begin
          Application.MessageBox(PChar('Erreur :  l''exécution de la commande a échoué !' + #13#10 + SysErrorMessage(GetLastError)), PChar(Caption + ' - erreur'), MB_ICONERROR + MB_OK);
          CloseHandle(hReadPipe);
          CloseHandle(hWritePipe);
          Exit;
       end;
     
       CloseHandle(hWritePipe);
       nBytesToRead := LENBUFF;
       nBytesRead := 0;
     
       szResult := '';
       while(True) do
       begin
          lpBuffer := '';
          ReadFile(hReadPipe, lpBuffer, nBytesToRead, nBytesRead, nil);
          if nBytesRead = 0 then
             Break;
          szResult := szResult + StrPas(lpBuffer);
       end;
     
       WaitForSingleObject(pi.hProcess, INFINITE);
       CloseHandle(pi.hProcess);
       CloseHandle(hReadPipe);
    Sous Delphi 2010, j'ai une violation d'accès dans 'kernel32.dll' au niveau de CreateProcess.

    J'ai essayé d'utiliser la version ansi (CreateProcessA), mais ça ne change rien.

    Une idée ?


  2. #2
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 457
    Points
    28 457
    Par défaut
    The Unicode version of this function, CreateProcessW, can modify the contents of this string. Therefore, this parameter cannot be a pointer to read-only memory (such as a const variable or a literal string). If this parameter is a constant string, the function may cause an access violation.
    sous XE ça passe avec ceci (temp:string)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
       temp := szCommande;
       if not CreateProcess(nil, @temp[1], nil, nil, True, 0, nil, nil, si, pi) then
    mais la réponse est zarbi...doit y avoir un pb unicode/ansi

  3. #3
    Membre chevronné
    Avatar de eric.pommereau
    Homme Profil pro
    Ingénieur, pôle cartographie
    Inscrit en
    Décembre 2004
    Messages
    715
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur, pôle cartographie
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Décembre 2004
    Messages : 715
    Points : 1 790
    Points
    1 790
    Par défaut
    Toujours au taquet sur Delphi Paul ;-)

  4. #4
    Expert éminent
    Avatar de Lung
    Profil pro
    Analyste-programmeur
    Inscrit en
    Mai 2002
    Messages
    2 674
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste-programmeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 2 674
    Points : 7 063
    Points
    7 063
    Par défaut
    Citation Envoyé par Paul TOTH Voir le message
    sous XE ça passe avec ceci (temp:string)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
       temp := szCommande;
       if not CreateProcess(nil, @temp[1], nil, nil, True, 0, nil, nil, si, pi) then
    mais la réponse est zarbi...doit y avoir un pb unicode/ansi
    J'ai essayé ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
       szTemp := szCommande;
     
       if not CreateProcess(nil, @szTemp[1], nil, nil, True, 0, nil, nil, si, pi) then
    Effectivement, ça ne plante plus.
    Mais, par contre le buffer (lpBuffer) contenant la valeur de retour de la commande, est rempli de #0
    Par sûr que ce soit bon signe.

  5. #5
    Expert éminent sénior
    Avatar de Cl@udius
    Homme Profil pro
    Développeur Web
    Inscrit en
    Février 2006
    Messages
    4 878
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Février 2006
    Messages : 4 878
    Points : 10 008
    Points
    10 008
    Par défaut
    Salut Lung

    A mon avis ta variable lpBuffer devrait être un array of AnsiChar.
    Ensuite il faudra certainement convertir le resultat de la lecture avec OemToAnsi ou OemToChar afin de gérer notamment les caractères accentués sous DOS.

    [edit]

    Après test, ceci me revoie un bel echo de la commande.
    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
     
    var
      // ...
      lpBuffer: array [0..LENBUFF] of AnsiChar;
      // ...
    begin
      // ...
      szResult := '';
      while True do
      begin
        lpBuffer := '';
        ReadFile(hReadPipe, lpBuffer, nBytesToRead, nBytesRead, nil);
        if nBytesRead = 0 then
          Break;
        OemToAnsi(lpBuffer, lpBuffer);
        szResult := szResult + string(lpBuffer);
      end;
      // ...

    @+ Claudius

  6. #6
    Expert éminent
    Avatar de Lung
    Profil pro
    Analyste-programmeur
    Inscrit en
    Mai 2002
    Messages
    2 674
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste-programmeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 2 674
    Points : 7 063
    Points
    7 063
    Par défaut
    Citation Envoyé par Cl@udius Voir le message
    A mon avis ta variable lpBuffer devrait être un array of AnsiChar.
    Ensuite il faudra certainement convertir le resultat de la lecture avec OemToAnsi ou OemToChar afin de gérer notamment les caractères accentués sous DOS.

    [edit]

    Après test, ceci me revoie un bel echo de la commande.
    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
     
    var
      // ...
      lpBuffer: array [0..LENBUFF] of AnsiChar;
      // ...
    begin
      // ...
      szResult := '';
      while True do
      begin
        lpBuffer := '';
        ReadFile(hReadPipe, lpBuffer, nBytesToRead, nBytesRead, nil);
        if nBytesRead = 0 then
          Break;
        OemToAnsi(lpBuffer, lpBuffer);
        szResult := szResult + string(lpBuffer);
      end;
      // ...
    Ca marche !!!

  7. #7
    Expert éminent sénior
    Avatar de Cl@udius
    Homme Profil pro
    Développeur Web
    Inscrit en
    Février 2006
    Messages
    4 878
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Février 2006
    Messages : 4 878
    Points : 10 008
    Points
    10 008
    Par défaut
    Citation Envoyé par Lung Voir le message
    Ca marche !!!
    Pas de quoi !
    @+

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

Discussions similaires

  1. Réponses: 6
    Dernier message: 20/01/2011, 11h52
  2. code en c# pour exécuter une commande dos en arrière plan
    Par GhostMoon dans le forum Windows Forms
    Réponses: 2
    Dernier message: 31/03/2010, 09h48
  3. Réponses: 3
    Dernier message: 25/09/2009, 11h48
  4. Fichier BATCH pour exécuter une commande (Wake on LAN)
    Par snoopy69 dans le forum Windows XP
    Réponses: 0
    Dernier message: 23/04/2008, 07h14
  5. Utiliser Createprocess pour lancer une fonction
    Par lolita4882 dans le forum C++
    Réponses: 3
    Dernier message: 14/03/2008, 12h01

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