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 :

[D6][Windows 10] Ma fiche fonctionne mais reste figée


Sujet :

Delphi

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre expérimenté
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    2 453
    Détails du profil
    Informations personnelles :
    Âge : 71
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 2 453
    Points : 1 337
    Points
    1 337
    Par défaut [D6][Windows 10] Ma fiche fonctionne mais reste figée
    Bonjour à toutes et à tous,

    En reprenant les exemples et conseils, j'ai testé pour ne pas mourir idiot le contenu d'un fichier batch dans une application.

    Elle fonctionne, le déroulement de ce contenu se fait mais la fome reste figée (pas moyen de la déplacée) pendant le traitement et l'affichage dans le Tmemo reste aussi figé.

    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
     
    procedure GetDosOutput(CommandLine, WorkDir: string;aMemo : TMEMO);
    var
      SA: TSecurityAttributes;
      SI: TStartupInfo;
      PI: TProcessInformation;
      StdOutPipeRead, StdOutPipeWrite: THandle;
      WasOK: Boolean;
      Buffer: array[0..255] of AnsiChar;
      BytesRead: Cardinal;
      Handle: Boolean;
     
    begin
      AMemo.Lines.Add('');
      AMemo.Lines.Add('Début de la conversion en mp4...');
      AMemo.Lines.Add('');
      with SA do begin
        nLength := SizeOf(SA);
        bInheritHandle := True;
        lpSecurityDescriptor := nil;
      end;
      CreatePipe(StdOutPipeRead, StdOutPipeWrite, @SA, 0);
      try
        with SI do
        begin
          FillChar(SI, SizeOf(SI), 0);
          cb := SizeOf(SI);
          dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
          wShowWindow := SW_HIDE;
          hStdInput := GetStdHandle(STD_INPUT_HANDLE); // don't redirect stdin
          hStdOutput := StdOutPipeWrite;
          hStdError := StdOutPipeWrite;
        end;
        Handle := CreateProcess(nil, PChar('cmd.exe /C ' + CommandLine),
                                nil, nil, True, 0, nil,
                                PChar(WorkDir), SI, PI);
        CloseHandle(StdOutPipeWrite);
        if Handle then
          try
            repeat
              WasOK := ReadFile(StdOutPipeRead, Buffer, 255, BytesRead, nil);
              if BytesRead > 0 then
              begin
                Buffer[BytesRead] := #0;
                OemToChar(Buffer,Buffer); //Pour caractères é....
                AMemo.Text := AMemo.Text + Buffer;
              end;
            until not WasOK or (BytesRead = 0);
            WaitForSingleObject(PI.hProcess, INFINITE);
          finally
            CloseHandle(PI.hThread);
            CloseHandle(PI.hProcess);
          end;
      finally
        CloseHandle(StdOutPipeRead);
        AMemo.Lines.Add('');
        AMemo.Lines.Add('Conversion terminée avec success.');
        AMemo.Lines.Add('');
        AMemo.Lines.Add('*****************************************');
        AMemo.Lines.Add('');
     
      end;
    end;
    usage :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    fichier := 'mkdir Conversion&&ffmpeg -i "concat:VTS_01_1.vob|VTS_01_2.vob|VTS_01_3.vob" -vcodec libx264 -crf 27 -preset veryfast -c:a copy -s 960x540 Conversion\'+Ednom.text+'.mp4'; //Code du fichier batch
     
    EdFichier.Text := fichier;
     
    cmd := fichier;
     
    GetDosOutput(cmd,chappli,Memo1);
    En utilisant un Tpanel et le fichier batch c'est impeccable.

    Je pensais que cette procédure que j'ai connue dans des topics avec ShaiLeTroll, fonctionnerait sans être figée peut être avec un fichier batch simple ?

    Si quelqu'un avait une idée cela m'intéresse.

    Bonne journée.

    @+,

    cincap

  2. #2
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 643
    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 643
    Points : 25 375
    Points
    25 375
    Par défaut
    Ce n'est pas du tout mon code de lecture de Pipes !
    Celle-ci confond les Pipe d'entrée et sortie avec les Pipes de lecture et écriture, c'est une veille erreur depuis longtemps corrigée.

    Redirection des entrées/sorties du process note le Application.ProcessMessages dans la CallBack pour TCallCmdEvent pour éviter le blocage mais ne pas oublier le INFINITE de WaitForSingleObject c'est surtout valable pour une CMD qui renvoie régulièrement du contenu mais si c'est plus rare, j'ai prévu un Délai pour gérer un Idle qui fera aussi le ProcessMessages, tous les 200ms c'est bien

    je te conseille d'ailleurs une version plus récente : TSLTShellExecuteWrapper.CallCmd (quoi qu'un peu trop récente pour gérer Unicode et 64 Bits)

    je n'ai rien inventé : Création d’un processus enfant avec une entrée et une sortie redirigées, un article par microsoft

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

    Informations forums :
    Inscription : Janvier 2006
    Messages : 2 453
    Points : 1 337
    Points
    1 337
    Par défaut
    @ ShaiLeTroll, merci de ta réponse,

    Ce n'est pas du tout mon code de lecture de Pipes !
    Celle-ci confond les Pipe d'entrée et sortie avec les Pipes de lecture et écriture, c'est une veille erreur depuis longtemps corrigée.
    Je savais que ce n'était pas ta solution, je l'indiquais :

    En reprenant les exemples et conseils
    Par contre j'avais aussi essayé ta solution et celle de Charly910 et j'avais le même problème.

    https://www.developpez.net/forums/d4...-process-ping/

    Je m'y prend certainement mal.

    Merci.

    @+,

    cincap

  4. #4
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 643
    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 643
    Points : 25 375
    Points
    25 375
    Par défaut
    Dans la version D7 de l'époque le code est pensé générique epcWindows.CallCmd reçoit en paramètre un CallBack, c'est un peu comme un gestionnaire d'évènement, dans ce cas c'était _ExportEvent qui manipulait le Mémo
    C'est le CallBack qui prend la responsabilité de gérer ou non la file de messages, j'ai préféré le gérer différemment selon le cas, tout simplement parce que c'est fonction a été utilisé en Thread donc hors de question de faire un ProcessMessages et encore, j'ai poussé le vice à invoquer un script PHP qui appelait le programme appelant par un objet OLE partagé donc la gestion inter-processus était bien plus complexe :
    - Quelle est la méthode propre pour éviter le TDispatchSilencer dans un EventSink
    - Faire un appel genre DCOM ou RPC sur deux instances déjà chargées sur le même PC

    A l'époque de D7 et WinXP, le Memo devait se rafraichir même si l'application autour semblait "gelé" avec Win10, la gestion des contrôles a changé et il me semble plus sensible à l'absence de l'écoute de la file des messages.
    Si tu reste sur ton code actuel, dans le repeat until, après le AMemo.Text, tu peux faire un ProcessMessages, mais vu la gueule de la boucle, elle doit charger bcp le CPU.
    Si tu tentes l'utilisation de CallCmd SANS la modifier pour conserver son aspect générique, l'encaspuler pour ajouter tes éléments perso et lui fournir un CallBack adapté, tu auras une lecture en temps réel du Pipe.

    AMemo.Text c'est aussi chronophage, j'utilise Lines.Add même si sur certaines sorties le résultat peut être erroné à l'affichage, c'est pour cela que j'utilisais plutôt le contenu de OutputText si je devais traiter le résultat, dans mon cas, un XML émis par Php.exe lorsque j'ai écrit cette fonction
    D'ailleurs en D6 OutputText := OutputText + DeltaOutputText est une opération lente sauf si tu as FastMM.

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

    Informations forums :
    Inscription : Janvier 2006
    Messages : 2 453
    Points : 1 337
    Points
    1 337
    Par défaut
    @ ShaiLeTroll, merci pour la suggestion du processmessages.

    J'obtiens déjà un mieux, la fiche n'est plus figée et le code se déroule bien seul bémol, le ScrollBarre reste à la 1ère ligne mais je sais le faire descendre alors qu'avant il était figé.

    Et chose étonnante le scrollbarre est bien à la dernière ligne lorsque le processus est terminé.

    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
     
    procedure GetDosOutput(CommandLine, WorkDir: string;aMemo : TMemo);
    var
      SA: TSecurityAttributes;
      SI: TStartupInfo;
      PI: TProcessInformation;
      StdOutPipeRead, StdOutPipeWrite: THandle;
      WasOK: Boolean;
      Buffer: array[0..255] of AnsiChar;
      BytesRead: Cardinal;
      Handle: Boolean;
    begin
      AMemo.Lines.Add('Conversion commencée...');
      AMemo.Lines.Add('');
      with SA do begin
        nLength := SizeOf(SA);
        bInheritHandle := True;
        lpSecurityDescriptor := nil;
      end;
      CreatePipe(StdOutPipeRead, StdOutPipeWrite, @SA, 0);
      try
        with SI do
        begin
          FillChar(SI, SizeOf(SI), 0);
          cb := SizeOf(SI);
          dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
          wShowWindow := SW_HIDE;
          hStdInput := GetStdHandle(STD_INPUT_HANDLE); // don't redirect stdin
          hStdOutput := StdOutPipeWrite;
          hStdError := StdOutPipeWrite;
        end;
        Handle := CreateProcess(nil, PChar('cmd.exe /C ' + CommandLine),
                                nil, nil, True, 0, nil,
                                PChar(WorkDir), SI, PI);
        CloseHandle(StdOutPipeWrite);
        if Handle then
          try
            repeat
              WasOK := ReadFile(StdOutPipeRead, Buffer, 255, BytesRead, nil);
              if BytesRead > 0 then
              begin
                Buffer[BytesRead] := #0;
                OemToAnsi(Buffer, Buffer);
                AMemo.Text := AMemo.Text + Buffer;
                Application.ProcessMessages; //suggestion de ShaiLeTroll
              end;
            until not WasOK or (BytesRead = 0);
            WaitForSingleObject(PI.hProcess, INFINITE);
          finally
            CloseHandle(PI.hThread);
            CloseHandle(PI.hProcess);
          end;
      finally
        CloseHandle(StdOutPipeRead);
        AMemo.Lines.Add('');
        AMemo.Lines.Add('Conversion terminée avec succès.');
        AMemo.Lines.Add('**********************************');
        AMemo.Lines.Add('');
      end;
    end;
    Je vais fermer le topic car je pense qu'il n'y aura pas d'autres solutions.

    Encore merci à toi.

    @+,

    cincap

  6. #6
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 643
    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 643
    Points : 25 375
    Points
    25 375
    Par défaut
    Pour le Defilement auto, je ne sais plus quel version gère cela pour le Lines.Add
    Pour .Text, EM_LINESCROLL comme dans TRichEdit : défilement vertical automatique (autoscrolling)

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

Discussions similaires

  1. Réponses: 10
    Dernier message: 28/10/2017, 21h56
  2. un programme windows qui fonctionne mais ne se ferme pas
    Par ketchupi dans le forum Débuter
    Réponses: 1
    Dernier message: 22/04/2011, 19h54
  3. Fiche créée mais pas reconnue par l'application ??
    Par Leesox dans le forum Langage
    Réponses: 8
    Dernier message: 30/10/2005, 15h10
  4. [WINDOWS CE]WriteProfileString ne fonctionne pas
    Par protonos dans le forum MFC
    Réponses: 17
    Dernier message: 13/05/2005, 19h58
  5. Réponses: 4
    Dernier message: 30/04/2004, 13h14

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