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 :

Redirection des entrées/sorties du process (ping)


Sujet :

Langage Delphi

  1. #21
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 911
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 911
    Points : 15 344
    Points
    15 344
    Par défaut
    Citation Envoyé par FabienManach Voir le message
    ce n'est pas le même langage mais les algos sont les mêmes !
    Certes, certes, mais des fois on débuggue mieux avec un IDE, et c'est pas sûr que tout le monde ait DevCpp ou Visual Studio ou ...
    (en plus, ch'suis au taf, là, et j'ai rien de chez rien... )
    --
    jp

  2. #22
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 613
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    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 613
    Points : 25 304
    Points
    25 304
    Par défaut
    les deux appels à WaitForSingleObject me choque, c'est soit l'un soit l'autre, depuis faire un CloseHandle du Thread appelé c'est étrange alors le process n'est pas fini, le CloseHandle doit être fait après le WaitForSingleObject(INFINITE)

    la MSDN Comment générer des processus de console avec les poignées standard redirigées devrait être une meilleure source ... tu noteras que c'est un mélange avec ma dernière variante, et celle de Paul TOTH, ...

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

    Informations forums :
    Inscription : Mai 2008
    Messages : 27
    Points : 27
    Points
    27
    Par défaut
    Merci beaucoup pour vos réponses !
    J'arrive maintenant à récupérer quelque chose, mais je ne suis pas sur que se soit une erreur du à l'execution de mon programme "Accès refusé" !
    Et toujours cette erreur !

    Je vais continuer à chercher je ne pense pas être loin !

    Et merci pour les liens Shai, J'avais déjà vu le lien avec la récupération au fil de l'eau, je m'y suis inspiré justement !

    Je n'ai pas l'habitude programmé sous Windows, ca change de Linux !

  4. #24
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 911
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 911
    Points : 15 344
    Points
    15 344
    Par défaut
    Citation Envoyé par FabienManach Voir le message
    J'arrive maintenant à récupérer quelque chose, mais je ne suis pas sur que se soit une erreur du à l'execution de mon programme "Accès refusé" !
    Problème de droits, et/ou de sécurité. Regarde le post de Shai du 9/01 à 20h39.
    Mes 2 cts,
    --
    jp

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

    Informations forums :
    Inscription : Mai 2008
    Messages : 27
    Points : 27
    Points
    27
    Par défaut
    Merci JP.

    Je pense en effet qu'il s'agisse de problème de droits, je travail sous Vista, et il est bien connu pour ces gestions un peu particulière des droits ...

    Je n'ai pas trouvé de poste datant du 9/01 dans les messages de Shai

    En tous les cas, merci pour toutes vos réponses

  6. #26
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 911
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 911
    Points : 15 344
    Points
    15 344
    Par défaut
    Citation Envoyé par FabienManach Voir le message
    Je n'ai pas trouvé de poste datant du 9/01 dans les messages de Shai
    Euh, là ?
    --
    jp

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

    Informations forums :
    Inscription : Mai 2008
    Messages : 27
    Points : 27
    Points
    27
    Par défaut
    Merci JP.

    J'avais effectivement déjà lu se post, il n'était pas très loin d'ailleurs !

    Mais je ne comprend pas bien un point:

    Shai cherche à lire le stdIn ? Moi j'ai besoin de récupérer la sortie d'erreur de la commande, donc plutôt stdErr voir stdOut non ?

    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
     
     
    if ( !CreatePipe(&PipeOutputRead,&PipeOutputWrite,&Security,0))
                              throw Erreur_Execution("impossible de lancé la procédure de configuration");
     
                           startupinfo.cb=sizeof(startupinfo);
                           startupinfo.dwFlags=STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
                           startupinfo.wShowWindow=SW_HIDE;
                           startupinfo.hStdInput = PipeOutputRead;
                           startupinfo.hStdOutput= PipeOutputWrite;
                           startupinfo.hStdError = PipeOutputWrite;
                           DWORD nLastError;
                           LPSTR lpMessageBuffer;
                                if (CreateProcess(NULL,szCmdline,&Security,&Security,TRUE,CREATE_NEW_CONSOLE,NULL,NULL,&startupinfo,&processinfo))
                                {
                                  
                                  WaitForSingleObject(processinfo.hProcess,INFINITE); 
                                  // fermer pipeOut Sinon on ne peut pas lire pipeIn
                                  CloseHandle(PipeOutputRead);
                                  PipeSize = GetFileSize(PipeOutputWrite, &PipeSizeHigh);
                                  PipeOutputRead=0;
                                  
                                  GetExitCodeProcess(processinfo.hProcess, &ret);
                                  if(ret != 0)
                                  {
                                         char Buffer[PipeSize];
                                         ZeroMemory(&Buffer[1], PipeSize);
                                         ReadFile(PipeOutputWrite,Buffer,PipeSize,&NbRead,NULL);
                                         message+=Buffer;
                                         nLastError = GetLastError();
                                         FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, nLastError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMessageBuffer, 0, NULL);    
                                    
                                  }
     
     
     
                                  if( ret != STILL_ACTIVE)
                                  {
                                      CloseHandle(processinfo.hThread);
                                      CloseHandle(processinfo.hProcess);
                                  } 
                                  else
                                  {
                                      CloseHandle(PipeOutputRead);
                                      
                                  }
                                  CloseHandle(PipeOutputWrite);
     
                                  CloseHandle(PipeOutputRead);
     
                                }
    avec ça, je ne récupère que le fameux "Accès refusé".
    J'ai bien essayer d'inverser et de lire stdIn, et donc ici PipeOutputRead, et la je récupère "le canal de communication a été coupé".

    j'avoue ne pas très bien comprendre .

  8. #28
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 613
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    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 613
    Points : 25 304
    Points
    25 304
    Par défaut
    Je n'essayais pas de lire StdIn, j'avais juste très mal codé ma fonction à ce moment là, et l'astuce était de faire un CloseHandle, pour pouvoir lire le pipe, ... ensuite, j'ai compris mon erreur, et j'ai donc corrigé en passant de 1 pipe à 3 pipes ... et personnellement, je n'ai aucun soucis, peut-être que ton programme interdit le détournement des canaux standards ...

  9. #29
    Membre éclairé Avatar de rt15
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2005
    Messages
    262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Octobre 2005
    Messages : 262
    Points : 665
    Points
    665
    Par défaut
    Salut,

    ShaiLeTroll -> Juste une remarque en passant . Dans ton exemple de la page précédente :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    var
      _AbortCallCmd: Boolean = False;
     
    procedure CallCmdEvent(const Output, Error: string; var AbortProcess: Boolean);
    begin
      MainForm.MemoOutput.Lines.Add(Output);
      MainForm.MemoError.Lines.Add(Error);
     
      Application.ProcessMessages();
      _AbortProcess := AbortCallCmd;
    end;
    Il me semble que tu voulais écrire :
    AbortProcess := _AbortCallCmd;

    de manière à ce que le processus soit arrêté si l'utilisateur le demande en cliquant sur le bouton.

    Bon ok c'est chercher la petite bête (Ou le gros troll ), mais ce serait dommage de laisser ça dans un si joli code (Encore que ça ressemble un peu trop à un timer à mon gout.).

  10. #30
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 613
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    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 613
    Points : 25 304
    Points
    25 304
    Par défaut
    Bien vu, surtout qu'en réalité dans mon code, j'ai ajouté un paramètre supplémentaire, le Parent, qui dans mon cas un en fait un objet transtypé à la sauvage, ce qui donnerait ceci en reprenant mon exemple

    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
    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;
        end;
      end;
    end;
    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
    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
       )
    end;
    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
    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
    unit epcWindows;
     
    interface
     
    uses Windows, SysUtils;
     
    {* -----------------------------------------------------------------------------
    TCallCmdEvent pointeur de procédure ...
    @param Parent identifiant privé utilisé dans WaitEvent fourni par la fonction appelante de CallCmd
    @param Output contiennent les derniers éléments envoyés par le programme console sur le canal StdOut
    @param Error contiennent les derniers éléments envoyés par le programme console sur le canal StdError
    @param AbortProcess indique si la processus doit être arrêté
    ------------------------------------------------------------------------------ }
    type
      TCallCmdEvent = procedure(Parent: Cardinal; const Output, Error: string; var AbortProcess: Boolean); stdcall;
     
    function CallCmd(const CmdDirectory, CmdName, CmdParam: string; out ExitCode: Int64; out OutputText: string; out ErrorText: string; Delay: Cardinal = INFINITE; Parent: Cardinal = 0; WaitEvent: TCallCmdEvent = nil; PipeMaxSize: Cardinal = 0): Boolean;
     
    implementation
     
    uses Math;
     
    {* -----------------------------------------------------------------------------
    la fonction CallCmd permet de lancer un programme console, tout en récupérant en quasi temps-réel le contenu devant normalement s'y afficher
    @param CmdDirectory Dossier contenant le Fichier CmdName
    @param CmdName programme console à executer
    @param CmdParam paramètres de la ligne de commande
    @param ExitCode Code de Sortie renvoyé par le programme console, -1 si non récupéré
    @param OutputText chaine contenant tout ce qui aurait du s'afficher (canal sortie)
    @param ErrorText chaine contenant tout ce qui a été signalé comme erreurs (canal erreur)
    @param Delay indique le temps entre chaque cycle de lecture des canaux, détermine la fréquence de lancement de WaitEvent, par défaut, cela attend que le programme console se termine
    @param Parent identifiant privé utilisé dans WaitEvent fourni par la fonction appelante de CallCmd
    @param WaitEvent procédure à lancer lorsque le Delay est écoulé, Output et Error contiennent les derniers éléments envoyés par le programme console sur les canaux depuis le dernier délai, AbortProcess indique si la processus doit être arrêté
    @param PipeMaxSize défini la taille maximal que l'on lit à chaque chaque cycle de lecture des canaux, si zéro, taille non limitée par défaut
    @return Indique si le programme a été lancé
    ------------------------------------------------------------------------------ }
    function CallCmd(const CmdDirectory, CmdName, CmdParam: string; out ExitCode: Int64; out OutputText: string; out ErrorText: string; Delay: Cardinal = INFINITE; Parent: Cardinal = 0; WaitEvent: TCallCmdEvent = nil; PipeMaxSize: Cardinal = 0): Boolean;
    var
      StartupInfo: TStartupInfo;
      ProcessInfo: TProcessInformation;
      CmdLine: string; // utile pour le débogage
      SecurityAttr : TSecurityAttributes;
      hReadPipeInput, hWritePipeInput: Cardinal;
      hReadPipeOutput, hWritePipeOutput: Cardinal;
      hReadPipeError, hWritePipeError: Cardinal;
      Terminated: Boolean;
      AbortProcess: Boolean;
      HandleFunctionProcess: Cardinal;
     
      function ReadPipe(Handle: Cardinal; out Buf: string): Boolean;
      const
        MAX_INT: Cardinal = MaxInt;
      var
        PipeSize: Cardinal;
        PipeToRead, PipeReaded: Cardinal;
      begin
        PipeSize := GetFileSize(Handle, nil); // On oublie si cela dépasse 2Go ... normalement c'est 4Ko
        if (PipeMaxSize > 0) and (PipeSize > PipeMaxSize) then
          PipeToRead := PipeMaxSize
        else
          PipeToRead := PipeSize;
     
        Result := PipeToRead > 0;
        if Result then
        begin
          SetLength(Buf, PipeToRead);
          ZeroMemory(@Buf[1], PipeToRead);
          ReadFile(Handle, Buf[1], PipeToRead, PipeReaded, nil);
        end;
      end;
     
      procedure ReadPipes();
      var
        DeltaOutputText: string;
        DeltaErrorText: string;
      begin
        if ReadPipe(hReadPipeOutput, DeltaOutputText) then
          OutputText := OutputText + DeltaOutputText;
        if ReadPipe(hReadPipeError, DeltaErrorText) then
          ErrorText := ErrorText + DeltaErrorText;
        try
          if Assigned(WaitEvent) then
            WaitEvent(Parent, DeltaOutputText, DeltaErrorText, AbortProcess);
        except
          on E: Exception do
            OutputDebugString(PChar(Format('epcWindows.CallCmd.ReadPipes.WaitEvent - "%s" : "%s"', [E.ClassName, E.Message])));
        end;
      end;
     
    begin
      (*
      Result := True;
      OutputText := 'Dummy Output';
      ErrorText := 'Dummy Error';
      ErrorCode := 0;
      Exit;
      *)
      OutputText := '';
      ErrorText := '';
      try
        SecurityAttr.nLength := SizeOf(TSecurityAttributes);
        SecurityAttr.lpSecurityDescriptor := nil;
        SecurityAttr.bInheritHandle := True;
        if CreatePipe(hReadPipeInput, hWritePipeInput, @SecurityAttr, 0) and
          CreatePipe(hReadPipeOutput, hWritePipeOutput, @SecurityAttr, 0) and
          CreatePipe(hReadPipeError, hWritePipeError, @SecurityAttr, 0) then
        begin
          try
            ZeroMemory(@StartupInfo, SizeOf(StartupInfo)); // GetStartupInfo(StartupInfo);
            StartupInfo.cb := SizeOf(StartupInfo);
            StartupInfo.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES; // Active wShowWindow et hStdOutput/hStdError
            StartupInfo.wShowWindow := SW_HIDE;
            StartupInfo.hStdInput := hReadPipeInput;
            StartupInfo.hStdOutput := hWritePipeOutput;
            StartupInfo.hStdError := hWritePipeError;
            ZeroMemory(@ProcessInfo, SizeOf(ProcessInfo));
            CmdLine := Format('"%s%s" %s', [IncludeTrailingPathDelimiter(CmdDirectory), CmdName, CmdParam]);
            Result := CreateProcess(nil, PChar(CmdLine), @SecurityAttr, @SecurityAttr, True, 0, nil, PChar(CmdDirectory), StartupInfo, ProcessInfo);
            if Result then
            begin
              try
                Terminated := False;
                AbortProcess := False;
                while not Terminated do
                begin
                  case WaitForSingleObject(ProcessInfo.hProcess, Delay) of
                    WAIT_OBJECT_0 :
                      begin
                        ReadPipes();
                        Terminated := True;
                      end;
                    WAIT_ABANDONED : Terminated := True;
                    WAIT_TIMEOUT :
                      begin
                        ReadPipes();
                        Terminated := Delay = INFINITE;
                      end;
                    WAIT_FAILED: Abort;
                  else
                    Terminated := True;
                  end;
     
                  if AbortProcess then
                  begin
                   HandleFunctionProcess := OpenProcess(PROCESS_TERMINATE, False, ProcessInfo.dwProcessId);
                   if HandleFunctionProcess > 0 then
                   begin
                     TerminateProcess(HandleFunctionProcess, 0);
                     CloseHandle(HandleFunctionProcess);
                   end;
                  end;
                end;
     
                TULargeInteger(ExitCode).HighPart := 0;
                if not GetExitCodeProcess(ProcessInfo.hProcess, TULargeInteger(ExitCode).LowPart) then
                  ExitCode := -1;
              finally
                CloseHandle(ProcessInfo.hThread);
                CloseHandle(ProcessInfo.hProcess); // The handles for both the process and the main thread must be closed through calls to CloseHandle
              end;
            end;
          finally
            CloseHandle(hReadPipeInput);
            CloseHandle(hWritePipeInput);
            CloseHandle(hReadPipeOutput);
            CloseHandle(hWritePipeOutput);
            CloseHandle(hReadPipeError);
            CloseHandle(hWritePipeError);
          end;
        end
        else
          raise Exception.Create('Impossible de créer les Pipes');
      except
        on E: Exception do
        begin
          OutputDebugString(PChar(Format('epcWindows.CallCmd Error %s, Message : %s', [E.ClassName, E.Message])));
          raise;
        end;
      end;
    end;
     
     
    end.

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 2 PremièrePremière 12

Discussions similaires

  1. rediriger des entrées/sorties
    Par the_only_kraft dans le forum Général Python
    Réponses: 2
    Dernier message: 12/09/2008, 13h34
  2. Adresse Mémoire des Entrées-Sorties
    Par B-NeT dans le forum Windows
    Réponses: 1
    Dernier message: 10/07/2008, 16h04
  3. Redirection des entrées ET sorties : << ET | tee
    Par Gaillac dans le forum Shell et commandes GNU
    Réponses: 5
    Dernier message: 24/04/2008, 16h44
  4. gestion des entrées-sorties
    Par bandit_debutant dans le forum Entrée/Sortie
    Réponses: 8
    Dernier message: 25/11/2006, 14h55

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