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

 Delphi Discussion :

Fenêtre Dos dans un TForm : comportement bizarre


Sujet :

Delphi

  1. #1
    Membre expérimenté
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    2 420
    Détails du profil
    Informations personnelles :
    Âge : 71
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 2 420
    Points : 1 325
    Points
    1 325
    Par défaut Fenêtre Dos dans un TForm : comportement bizarre
    Windows 10 64bits et D6

    Bonjour à toutes et à tous,

    Avec un fichier .bat, qui est exécuté avec un double click, les séquences se déroulent normalement jusqu'à la fin.

    Si j'affiche la fenêtre Dos dans une Tform, la fonte du texte de ce fichier .bat est différente (un peu moins nette) et le déroulement se fait mais l'affichage n'indique pas la fin pour répondre à la question qui permet de Quitter.

    Avez-vous constaté ce problème ?

    Et si il y a une solution pour améliorer cet affichage, je suis preneur.

    @+,

    cincap

  2. #2
    Membre émérite
    Avatar de ALWEBER
    Homme Profil pro
    Expert Delphi
    Inscrit en
    Mars 2006
    Messages
    1 490
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Expert Delphi

    Informations forums :
    Inscription : Mars 2006
    Messages : 1 490
    Points : 2 752
    Points
    2 752
    Billets dans le blog
    10
    Par défaut
    Bonjour, tu peux nous donner un petit exemple ?

  3. #3
    Membre expérimenté
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    2 420
    Détails du profil
    Informations personnelles :
    Âge : 71
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 2 420
    Points : 1 325
    Points
    1 325
    Par défaut
    Bonjour à toutes et à tous,

    @ ALWEBER, merci pour ton message.

    A ce sujet :

    mais l'affichage n'indique pas la fin pour répondre à la question qui permet de Quitter
    J'ai modifié mon fichier de test .bat en enlevant dans le code "PAUSE" avant le choix pour quitter.

    Pour l'autre question, d'après mes recherches il n'y a pas de solution.

    Si j'affiche la fenêtre Dos dans une Tform, la fonte du texte de ce fichier .bat est différente (un peu moins nette)...
    @+,

    cincap

  4. #4
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 447
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    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 447
    Points : 24 849
    Points
    24 849
    Par défaut
    Citation Envoyé par cincap Voir le message
    Si j'affiche la fenêtre Dos dans une Tform
    C'est cette phrase qui est obscure, est-via
    un FindWindow+SetParent ?
    un AllocConsole ?
    une TForm+TMemo+Redirection des Pipes ?
    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 expert
    Avatar de Charly910
    Homme Profil pro
    Ingénieur TP
    Inscrit en
    Décembre 2006
    Messages
    2 344
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur TP
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 344
    Points : 3 122
    Points
    3 122
    Par défaut
    Bonjour Cincap,

    si tu veux afficher le résultat d'une commande DOS dans un Memo (?), as tu essayé ceci :

    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
    procedure RunDosInMemo(DosApp:String;AMemo:TMemo);
    const
      ReadBuffer = 2400;
    var
      Security : TSecurityAttributes;
      ReadPipe,WritePipe : THandle;
      start : TStartUpInfo;
      ProcessInfo : TProcessInformation;
      Buffer : Pchar;
      BytesRead : DWord;
      Apprunning : DWord;
    begin
        With Security do begin
          nlength := SizeOf(TSecurityAttributes);
          binherithandle := true;
          lpsecuritydescriptor := nil;
        end;
     
        if Createpipe (ReadPipe, WritePipe, @Security, 0) then
          begin
            Buffer := AllocMem(ReadBuffer + 1);
            FillChar(Start,Sizeof(Start),#0);
            start.cb := SizeOf(start);
            start.hStdOutput := WritePipe;
            start.hStdInput := ReadPipe;
            start.dwFlags := STARTF_USESTDHANDLES +
            STARTF_USESHOWWINDOW;
            start.wShowWindow := SW_HIDE;
     
     
            if CreateProcess(nil, PChar(DosApp), @Security, @Security, true,
               NORMAL_PRIORITY_CLASS, nil, nil, start, ProcessInfo) then
              begin
                repeat
                  Apprunning := WaitForSingleObject
                  (ProcessInfo.hProcess,100);
                  Application.ProcessMessages;
                until (Apprunning <> WAIT_TIMEOUT);
                Repeat
                  BytesRead := 0;
                  ReadFile(ReadPipe,Buffer[0],
                  ReadBuffer,BytesRead,nil);
                  Buffer[BytesRead]:= #0;
                  OemToAnsi(Buffer,Buffer);
                  AMemo.Text := AMemo.text + String(Buffer);
                until (BytesRead < ReadBuffer);
              end;
            FreeMem(Buffer);
            CloseHandle(ProcessInfo.hProcess);
            CloseHandle(ProcessInfo.hThread);
            CloseHandle(ReadPipe);
            CloseHandle(WritePipe);
          end;
    end;
     
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      Memo1.Clear;
      Memo1.Color:=clblack;
      Memo1.Font.Color:=clwhite;
      RunDosInMemo('cmd /C DIR *.*',Memo1);
    end;
    (code pêché sur le net)

    La police de caractère est nette, c'est celle du Memo.

    A+
    Charly

  6. #6
    Membre expérimenté
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    2 420
    Détails du profil
    Informations personnelles :
    Âge : 71
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 2 420
    Points : 1 325
    Points
    1 325
    Par défaut
    @ ShaiLeTroll, merci de ton message, en fait j'affiche la fenêtre Dos sur un Tpanel donc :

    un FindWindow+SetParent ?
    Le texte est certainement moins net du fait de la mesure du Tpanel car quand je l'agrandis je constate que c'est normal, désolé.

    @ Charly910, merci aussi de ta réponse, je vais tester ta suggestion si je sais répondre aux questions directement du Tmemo, je n'ai jamais essayé cette pratique.

    Car je dois charger un fichier .bat

    Je vous tiens au courant.

    Merci à tous,

    @+,

    cincap

  7. #7
    Membre expert
    Avatar de Charly910
    Homme Profil pro
    Ingénieur TP
    Inscrit en
    Décembre 2006
    Messages
    2 344
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur TP
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 344
    Points : 3 122
    Points
    3 122
    Par défaut
    Pas de problème, ça marche aussi avec un fichier batch :

    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
    { ============================================================================== }
    procedure RunBatInMemo(FicBat:String;AMemo:TMemo);
    const
      ReadBuffer = 2400;
    var
      Security : TSecurityAttributes;
      ReadPipe,WritePipe : THandle;
      start : TStartUpInfo;
      ProcessInfo : TProcessInformation;
      Buffer : Pchar;
      BytesRead : DWord;
      Apprunning : DWord;
    begin
        With Security do begin
          nlength := SizeOf(TSecurityAttributes);
          binherithandle := true;
          lpsecuritydescriptor := nil;
        end;
     
        if Createpipe (ReadPipe, WritePipe, @Security, 0) then
          begin
            Buffer := AllocMem(ReadBuffer + 1);
            FillChar(Start,Sizeof(Start),#0);
            start.cb := SizeOf(start);
            start.hStdOutput := WritePipe;
            start.hStdInput := ReadPipe;
            start.dwFlags := STARTF_USESTDHANDLES +
            STARTF_USESHOWWINDOW;
            start.wShowWindow := SW_HIDE;
            if CreateProcess(nil, PChar(FicBat), @Security, @Security, true,
               NORMAL_PRIORITY_CLASS, nil, nil, start, ProcessInfo) then
              begin
                repeat
                  Apprunning := WaitForSingleObject
                  (ProcessInfo.hProcess,100);
                  Application.ProcessMessages;
                until (Apprunning <> WAIT_TIMEOUT);
                Repeat
                  BytesRead := 0;
                  ReadFile(ReadPipe,Buffer[0],
                  ReadBuffer,BytesRead,nil);
                  Buffer[BytesRead]:= #0;
                  OemToAnsi(Buffer,Buffer);
                  AMemo.Text := AMemo.text + String(Buffer);
                until (BytesRead < ReadBuffer);
              end;
            FreeMem(Buffer);
            CloseHandle(ProcessInfo.hProcess);
            CloseHandle(ProcessInfo.hThread);
            CloseHandle(ReadPipe);
            CloseHandle(WritePipe);
          end;
    end;
    { ============================================================================== }
    procedure TForm1.Button2Click(Sender: TObject);
    Var
      NomFichier : String ;
    begin
      Memo1.Clear;
      Memo1.Color:=clblack;
      Memo1.Font.Color:=clwhite;
      NomFichier := IncludeTrailingPathDelimiter(ExtractFilePath(Application.ExeName))+'Fichierbat.bat' ;
      RunDosInMemo(NomFichier,Memo1);
    end;
    { ============================================================================== }
    A+
    Charly

  8. #8
    Membre expérimenté
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    2 420
    Détails du profil
    Informations personnelles :
    Âge : 71
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 2 420
    Points : 1 325
    Points
    1 325
    Par défaut
    @ Charly910, j'ai testé et cela fonctionne très bien avec une fenêtre Dos, je suis surpris.

    Par contre avec le fichier . bat, cela ne fonctionne pas et j'ai difficile de fermer l'application.

    J'en profite pour te signaler dans ton dernier code un oubli du nom du changement de la procédure, cela m'arrive aussi avec les tests.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    procedure RunBatInMemo(FicBat:String;AMemo:TMemo);
    const
      ReadBuffer = 2400;
    Execution :

    RunDosInMemo(NomFichier,Memo1);
    L'écran reste noir et bloque l'application.

    @+,

    cincap

  9. #9
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 447
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    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 447
    Points : 24 849
    Points
    24 849
    Par défaut
    Mon Code proche de celui de Charly910, directement inspiré d'un Code C++ de la MSDN
    Disons qu'il y a une subtilité sur les Pipes pour justement pouvoir lire et écrire
    Pour cela, il faut faire WriteFile sur le handle hWritePipeInput (il faut bien différencié les Read/Write de In/Out/Error, une erreur fréquente c'est de les mélanger)

    Ce CallCmd a été utilisé en PROD avec EXE (PHP.exe) ainsi que des BAT avec Delphi 7

    Une version XE2 existe aussi TSLTShellExecuteWrapper.CallCmd exclusivement en PROD pour des BATL
    L'unité complète
    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

  10. #10
    Membre expérimenté
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    2 420
    Détails du profil
    Informations personnelles :
    Âge : 71
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 2 420
    Points : 1 325
    Points
    1 325
    Par défaut
    @ ShaiLeTroll, merci de ton aide,

    Avec ton exemple j'ai deux erreurs :

    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
    
    uses epcWindows;
    
    procedure _ExportEvent(Parent: Cardinal; const Output, Error: string; var AbortProcess: Boolean); stdcall;
    begin
      if Parent > 0 then
      begin
        with TMainForm(Parent) do
        begin
          if Output > '' then
            MemoOutput.Lines.Add(Output);
    
          if Output > '' then
            MemoError.Lines.Add(Error);
    
          AbortProcess := BtnCancel.Down; //Ici
        end;
      end;
    end;
    
    procedure TMainform.BtnTestDOSClick(Sender: TObject);
    var
        ExitCode: Int64;
        OutPutText: string;
        ErrorText: string;
    begin
     epcWindows.CallCmd(
        ExtractFileDir(Application.ExeName),
        'TestLong.Bat',
        '',
        ExitCode,
        OutPutText,
        ErrorText,
        10,
        Cardinal(Self),
        @CallCmdEvent //Ici
       )
    
    end;
    Je constate que cette façon de faire est quand même compliquée mais c'est comme une leçon.

    @+,

    cincap

  11. #11
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 447
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    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 447
    Points : 24 849
    Points
    24 849
    Par défaut
    @CallCmdEvent doit être remplacé par @_ExportEvent, d'ailleurs rt15 avait signalé que je collais des exemples pas tous raccords entre eux mais cela se comprend très vite

    Profite donc de la "leçon" est étudiant le code de plus près,
    la réponse était au problème de @CallCmdEvent était particulièrement triviale et l'ajout d'un TSpeedButton BtnCancel dans ta fenêtre semble tout aussi évident

    Citation Envoyé par cincap Voir le message
    Je constate que cette façon de faire est quand même compliquée
    Pour moi c'est assez simple comme code et cette LA façon officielle : Creating a Child Process with Redirected Input and Output

    je n'ai rien inventé, j'ai juste traduit une ancienne version de cet exemple
    le WriteToPipe devrait t'intéresser pour gérer la pause

    Code c++ : 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
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
     
    #include <windows.h> 
    #include <tchar.h>
    #include <stdio.h> 
    #include <strsafe.h>
     
    #define BUFSIZE 4096 
     
    HANDLE g_hChildStd_IN_Rd = NULL;
    HANDLE g_hChildStd_IN_Wr = NULL;
    HANDLE g_hChildStd_OUT_Rd = NULL;
    HANDLE g_hChildStd_OUT_Wr = NULL;
     
    HANDLE g_hInputFile = NULL;
     
    void CreateChildProcess(void); 
    void WriteToPipe(void); 
    void ReadFromPipe(void); 
    void ErrorExit(PTSTR); 
     
    int _tmain(int argc, TCHAR *argv[]) 
    { 
       SECURITY_ATTRIBUTES saAttr; 
     
       printf("\n->Start of parent execution.\n");
     
    // Set the bInheritHandle flag so pipe handles are inherited. 
     
       saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 
       saAttr.bInheritHandle = TRUE; 
       saAttr.lpSecurityDescriptor = NULL; 
     
    // Create a pipe for the child process's STDOUT. 
     
       if ( ! CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0) ) 
          ErrorExit(TEXT("StdoutRd CreatePipe")); 
     
    // Ensure the read handle to the pipe for STDOUT is not inherited.
     
       if ( ! SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0) )
          ErrorExit(TEXT("Stdout SetHandleInformation")); 
     
    // Create a pipe for the child process's STDIN. 
     
       if (! CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0)) 
          ErrorExit(TEXT("Stdin CreatePipe")); 
     
    // Ensure the write handle to the pipe for STDIN is not inherited. 
     
       if ( ! SetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0) )
          ErrorExit(TEXT("Stdin SetHandleInformation")); 
     
    // Create the child process. 
     
       CreateChildProcess();
     
    // Get a handle to an input file for the parent. 
    // This example assumes a plain text file and uses string output to verify data flow. 
     
       if (argc == 1) 
          ErrorExit(TEXT("Please specify an input file.\n")); 
     
       g_hInputFile = CreateFile(
           argv[1], 
           GENERIC_READ, 
           0, 
           NULL, 
           OPEN_EXISTING, 
           FILE_ATTRIBUTE_READONLY, 
           NULL); 
     
       if ( g_hInputFile == INVALID_HANDLE_VALUE ) 
          ErrorExit(TEXT("CreateFile")); 
     
    // Write to the pipe that is the standard input for a child process. 
    // Data is written to the pipe's buffers, so it is not necessary to wait
    // until the child process is running before writing data.
     
       WriteToPipe(); 
       printf( "\n->Contents of %s written to child STDIN pipe.\n", argv[1]);
     
    // Read from pipe that is the standard output for child process. 
     
       printf( "\n->Contents of child process STDOUT:\n\n", argv[1]);
       ReadFromPipe(); 
     
       printf("\n->End of parent execution.\n");
     
    // The remaining open handles are cleaned up when this process terminates. 
    // To avoid resource leaks in a larger application, close handles explicitly. 
     
       return 0; 
    } 
     
    void CreateChildProcess()
    // Create a child process that uses the previously created pipes for STDIN and STDOUT.
    { 
       TCHAR szCmdline[]=TEXT("child");
       PROCESS_INFORMATION piProcInfo; 
       STARTUPINFO siStartInfo;
       BOOL bSuccess = FALSE; 
     
    // Set up members of the PROCESS_INFORMATION structure. 
     
       ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
     
    // Set up members of the STARTUPINFO structure. 
    // This structure specifies the STDIN and STDOUT handles for redirection.
     
       ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
       siStartInfo.cb = sizeof(STARTUPINFO); 
       siStartInfo.hStdError = g_hChildStd_OUT_Wr;
       siStartInfo.hStdOutput = g_hChildStd_OUT_Wr;
       siStartInfo.hStdInput = g_hChildStd_IN_Rd;
       siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
     
    // Create the child process. 
     
       bSuccess = CreateProcess(NULL, 
          szCmdline,     // command line 
          NULL,          // process security attributes 
          NULL,          // primary thread security attributes 
          TRUE,          // handles are inherited 
          0,             // creation flags 
          NULL,          // use parent's environment 
          NULL,          // use parent's current directory 
          &siStartInfo,  // STARTUPINFO pointer 
          &piProcInfo);  // receives PROCESS_INFORMATION 
     
       // If an error occurs, exit the application. 
       if ( ! bSuccess ) 
          ErrorExit(TEXT("CreateProcess"));
       else 
       {
          // Close handles to the child process and its primary thread.
          // Some applications might keep these handles to monitor the status
          // of the child process, for example. 
     
          CloseHandle(piProcInfo.hProcess);
          CloseHandle(piProcInfo.hThread);
       }
    }
     
    void WriteToPipe(void) 
     
    // Read from a file and write its contents to the pipe for the child's STDIN.
    // Stop when there is no more data. 
    { 
       DWORD dwRead, dwWritten; 
       CHAR chBuf[BUFSIZE];
       BOOL bSuccess = FALSE;
     
       for (;;) 
       { 
          bSuccess = ReadFile(g_hInputFile, chBuf, BUFSIZE, &dwRead, NULL);
          if ( ! bSuccess || dwRead == 0 ) break; 
     
          bSuccess = WriteFile(g_hChildStd_IN_Wr, chBuf, dwRead, &dwWritten, NULL);
          if ( ! bSuccess ) break; 
       } 
     
    // Close the pipe handle so the child process stops reading. 
     
       if ( ! CloseHandle(g_hChildStd_IN_Wr) ) 
          ErrorExit(TEXT("StdInWr CloseHandle")); 
    } 
     
    void ReadFromPipe(void) 
     
    // Read output from the child process's pipe for STDOUT
    // and write to the parent process's pipe for STDOUT. 
    // Stop when there is no more data. 
    { 
       DWORD dwRead, dwWritten; 
       CHAR chBuf[BUFSIZE]; 
       BOOL bSuccess = FALSE;
       HANDLE hParentStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
     
       for (;;) 
       { 
          bSuccess = ReadFile( g_hChildStd_OUT_Rd, chBuf, BUFSIZE, &dwRead, NULL);
          if( ! bSuccess || dwRead == 0 ) break; 
     
          bSuccess = WriteFile(hParentStdOut, chBuf, 
                               dwRead, &dwWritten, NULL);
          if (! bSuccess ) break; 
       } 
    } 
     
    void ErrorExit(PTSTR lpszFunction) 
     
    // Format a readable error message, display a message box, 
    // and exit from the application.
    { 
        LPVOID lpMsgBuf;
        LPVOID lpDisplayBuf;
        DWORD dw = GetLastError(); 
     
        FormatMessage(
            FORMAT_MESSAGE_ALLOCATE_BUFFER | 
            FORMAT_MESSAGE_FROM_SYSTEM |
            FORMAT_MESSAGE_IGNORE_INSERTS,
            NULL,
            dw,
            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
            (LPTSTR) &lpMsgBuf,
            0, NULL );
     
        lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, 
            (lstrlen((LPCTSTR)lpMsgBuf)+lstrlen((LPCTSTR)lpszFunction)+40)*sizeof(TCHAR)); 
        StringCchPrintf((LPTSTR)lpDisplayBuf, 
            LocalSize(lpDisplayBuf) / sizeof(TCHAR),
            TEXT("%s failed with error %d: %s"), 
            lpszFunction, dw, lpMsgBuf); 
        MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK); 
     
        LocalFree(lpMsgBuf);
        LocalFree(lpDisplayBuf);
        ExitProcess(1);
    }
    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

  12. #12
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2011
    Messages
    4 070
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 4 070
    Points : 15 454
    Points
    15 454
    Billets dans le blog
    9
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    @CallCmdEvent doit être remplacé par @_ExportEvent, d'ailleurs rt15 avait signalé que je collais des exemples pas tous raccords entre eux mais cela se comprend très vite.

    Profite donc de la "leçon" en étudiant le code de plus près, la réponse au problème de @CallCmdEvent était particulièrement triviale et l'ajout d'un TSpeedButton BtnCancel dans ta fenêtre semble tout aussi évident.
    Bonjour ! C'est vrai qu'en se penchant sur le code et en lisant la discussion on peut assez facilement trouver les modifications à faire. Mais en même temps la vie est courte et la réaction de certains utilisateurs sera, si ça ne marche pas du premier coup, de mettre tout à la corbeille et de passer à autre chose. Personnellement, je trouve que ce code mériterait d'être bien présenté et ajouté dans les sources Delphi.
    Mon site personnel consacré à MSEide+MSEgui : msegui.net

  13. #13
    Membre expérimenté
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    2 420
    Détails du profil
    Informations personnelles :
    Âge : 71
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 2 420
    Points : 1 325
    Points
    1 325
    Par défaut
    Bonjour à toutes et à tous,

    @ Roland Chastin, merci de ta remarque qui est en partie vraie car je me fait une bibliothèque de suggestions et au bout d'un temps j'y reviens.

    D'un autre coté, ShaiLeTroll as aussi raison de laisser chercher aux débutants la solution.

    Pour ma part, mon code avec "HWND ef FindWindow() " me suffit pour le moment.

    Charly910 avait aussi une excellente suggestion et mon fichier .bat de test n'affichait que la dernière ligne et mon fichier .bat un écran noir.

    Apparemment, il exécute le fichier .bat en répondant au questions avant de l'afficher pour permettre d'y répondre !

    Fichier .bat de test :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    @echo off
    set /P Nom="Comment t'appelles-tu ? "
    echo Bonjour %Nom%
    set /p Age="Quel âge as-tu ? "
    set /a reste=65-Age
    echo Encore %reste% ans de turbin avant la retraite!
    pause
    Réponse telle quelle que l'on voit dans la fenêtre :

    ncore 65 ans de turbin avant la retraite!
    Appuyez sur une touche pour continuer...
    @ +,

    cincap

  14. #14
    Membre expert
    Avatar de Charly910
    Homme Profil pro
    Ingénieur TP
    Inscrit en
    Décembre 2006
    Messages
    2 344
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur TP
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 344
    Points : 3 122
    Points
    3 122
    Par défaut
    Bonjour,

    pour moi les 2 codes fonctionnent bien. Le bat peut comporter des paramètres mais bien sûr par d'interaction avec l'utilisateur (sinon l'application se fige).

    Simple inconvénient du code de ShaiLeTroll : les caractères accentués s'affichent mal (accents et séparateurs des milliers des tailles de fichier pour le Dir *.*).

    A+
    Charly

  15. #15
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 447
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    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 447
    Points : 24 849
    Points
    24 849
    Par défaut
    Citation Envoyé par Charly910 Voir le message
    Simple inconvénient du code de ShaiLeTroll : les caractères accentués s'affichent mal (accents et séparateurs des milliers des tailles de fichier pour le Dir *.*).
    Il doit être nécessaire d'ajouter un CharToOem (ou AnsiToOEM) dans _ExportEvent
    Je sais que je l'ajoutais pour générer des fichiers BAT exécutés à la volé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

  16. #16
    Membre expert
    Avatar de Charly910
    Homme Profil pro
    Ingénieur TP
    Inscrit en
    Décembre 2006
    Messages
    2 344
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur TP
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 344
    Points : 3 122
    Points
    3 122
    Par défaut
    @ShaiLeTroll :

    c'est curieux mais ni CharToOem, ni AnsiToOem n'ont l'air de régler le problème :

    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
     
    //  Uses epcWindows
    { ============================================================================== }
    Function ConvertToOem(Const s : String ) : String ;
    Begin
      SetLength(Result, Length(s)) ;
      If (Length(Result) > 0) Then
        CharToOem(PChar(s), PChar(Result)) ;
    End ;
    { ============================================================================== }
    procedure _ExportEvent(Parent: Cardinal; const Output, Error: string; var AbortProcess: Boolean); stdcall;
    begin
      if Parent > 0 then
      begin
        with TForm1(Parent) do
        begin
          if Output > '' then
            Begin
              Memo1.Lines.Add(ConvertToOem(Output));
            End ;
          if Output > '' then
            MemoError.Lines.Add(Error);
     
          AbortProcess := BtnCancel.Down;
        end;
      end;
    end;
    { ============================================================================== }
    procedure TForm1.Button4Click(Sender: TObject);
    var
      ExitCode: Int64;
      OutPutText: string;
      ErrorText: string;
      NomFichier : String ;
      Rep        : String ;
      Param      : String ;
    begin
      Memo1.Clear;
      Memo1.Color:=clblack;
      Memo1.Font.Color:=clwhite;
      Rep := IncludeTrailingPathDelimiter(ExtractFilePath(Application.ExeName)) ;
      NomFichier := 'Fichierbat.bat' ;
      Param := 'Coucou' ;
      epcWindows.CallCmd( Rep, NomFichier, Param, ExitCode, OutPutText,
                          ErrorText, 10, Cardinal(Self), @_ExportEvent )
    end;
    { ============================================================================== }
    Sauf si je m'y prend mal ?

    A+
    Charly

  17. #17
    Membre expert
    Avatar de Charly910
    Homme Profil pro
    Ingénieur TP
    Inscrit en
    Décembre 2006
    Messages
    2 344
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur TP
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 344
    Points : 3 122
    Points
    3 122
    Par défaut
    Que je suis bête, c'est OemToChar qu'il faut utiliser et non CharToOem !!!

    A+
    Charly

  18. #18
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2011
    Messages
    4 070
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 4 070
    Points : 15 454
    Points
    15 454
    Billets dans le blog
    9
    Par défaut
    Tiens, je ne savais pas qu'on pouvait écrire des choses comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    AbortProcess := BtnCancel.Down;
    Dans la démo que je m'étais faite pour moi-même, j'avais fait comme ceci.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    AbortProcess := CheckBoxAbortProcess.Checked;
    [HS]
    Pour compiler la version XE2 de l'unité (de ShaiLeTroll) avec le dernier Delphi il faut faire une petite modification.
    [/HS]
    Mon site personnel consacré à MSEide+MSEgui : msegui.net

  19. #19
    Membre expert
    Avatar de Charly910
    Homme Profil pro
    Ingénieur TP
    Inscrit en
    Décembre 2006
    Messages
    2 344
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur TP
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 344
    Points : 3 122
    Points
    3 122
    Par défaut
    Avec D7, la propriété Down d'un TSpeedButton est un Booléen donc :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    AbortProcess := BtnCancel.Down;
    ne m'a pas posé aucun problème.

    A+
    Chayly

Discussions similaires

  1. Réponses: 4
    Dernier message: 20/04/2011, 11h20
  2. Redimensionner une fenêtre DOS dans un batch.
    Par derfatypik dans le forum Windows
    Réponses: 2
    Dernier message: 20/09/2007, 14h44
  3. Fermer une fenêtre DOS dans une application MFC
    Par Jahjouh dans le forum Visual C++
    Réponses: 4
    Dernier message: 19/01/2007, 14h29
  4. Réponses: 11
    Dernier message: 06/12/2005, 08h23
  5. fenetre dos dans une application
    Par jfb53 dans le forum C++Builder
    Réponses: 3
    Dernier message: 19/10/2003, 18h06

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