Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Ausführung in sichtbarer Konsole und Inhalt der Konsole (Text) abfragen (https://www.delphipraxis.net/205707-ausfuehrung-sichtbarer-konsole-und-inhalt-der-konsole-text-abfragen.html)

Paul Schmidt 8. Okt 2020 09:37

Ausführung in sichtbarer Konsole und Inhalt der Konsole (Text) abfragen
 
Hallo liebe Gemeinde!

Ich rufe per CreateProcess ein externes Programm auf (genauer: git).
Dieses wird in einer Konsole ausgeführt, abgearbeitet und bei Beendigung wieder geschlossen.

Eigentlich hatte ich vor, das Konsolenfenster gar nicht anzuzeigen und die Ausgabe der Konsole bzw. des externen Programms (hier: git) "live" in einem Memo anzuzeigen, allerdings habe ich bis heute hierzu noch keine wirkliche Lösung gefunden, da alle Ansätze darauf beruhen, die Ausgabe der Konsole erst NACH Beendigung abzurufen.

In meinem Fall (git) ist es allerdings so, dass beim Hoch- oder Herunterladen (pull, push) in der Konsole der Down/Upload Fortschritt angezeigt wird. Und hier ist es offenbar nicht möglich, solche Ausgaben wirklich zeitgleich abzufragen.


Nun war meine Idee, dass ich für den Aufruf via CreateProcess das Konsole-Fenster einfach anzeigen lasse. Das funktioniert auch.
ABER: ich möchte gern bei Beendigung des Aufrufes den Inhalt des Konsolen-Fensters in einem String speichern.
Nur weiß ich nicht, wie ich das anstellen kann.

Also: ich möchte den Aufruf per CreateProcess in einem sichtbaren Konsolen-Fenster ausführen lassen, aber anschließend dessen Inhalt in einem String speichern/abrufen.

Kann mir jemand dabei bitte helfen? :?:
Alle bisher gefundenen Ansätze lassen entweder nur die Ausgabe in eine Pipe oder die Anzeige des Konsolen-Fensters zu.
Nicht aber das nachträgliche Abrufen des Inhalts des Konsolen-Fensters (bei Beendigung des Prozesses).

Herzlichen Dank im Voraus! :)

Grüße,
Paul

CCRDude 8. Okt 2020 10:07

AW: Ausführung in sichtbarer Konsole und Inhalt der Konsole (Text) abfragen
 
Die Pipe ist doch schon der richtige Ansatz! Bzw. zwei davon, stdout und errout. Ob während der Laufzeit oder danach liefern sie die Ausgaben. In den STARTUPINFO von CreateProcess musst Du die Pipes halt angeben. Dann geht das Live.

Das später aus einem Terminal auszulesen dürfte ungleich schwieriger sein.

Paul Schmidt 8. Okt 2020 12:17

AW: Ausführung in sichtbarer Konsole und Inhalt der Konsole (Text) abfragen
 
Das Problem bzgl. Pipe ist, dass es eigentlich für 95% der Fälle funktioniert. Nur eben für den entsprechenden Aufruf (push) nicht, welcher eine Ausgabe in der Konsole erzeugt, die einen Upload-Fortschritt anzeigt: gleichbleibende Zeile mit aufsteigenden Prozent-Werten
So in der Art:
[10 / 20] 30%

(und dann eben in der gleichen Zeile: [14 / 20] 57% usw.)

Die sonstigen Aufrufe von git (wie bspw. "init", "status", usw.) funktionieren.

Deshalb weiß ich im Moment nicht, wo der Fehler hierbei liegt bzw. wie ich das korrigieren kann.

CCRDude 8. Okt 2020 12:45

AW: Ausführung in sichtbarer Konsole und Inhalt der Konsole (Text) abfragen
 
Was genau funktioniert dabei denn nicht? Das "In der Zeile" läuft über CR statt CRLF. Trennt man den String aus der Pipe grob, hat man das CR als komplett neue Zeile, dann steht der Fortschritt unschön untereinander.

Alternative 1: In meinem Lazarus VCS Helper löse ich das Problem anders - dort steuere ich TortoiseGit, das bringt das UI für viele Operationen gleich mit.

Alternative 2: direkt libgit2 zu verwenden. Habe ich mal angefangen, aber weil obiges so gut funktioniert nicht weitergeführt (auch im verlinkten repository).

himitsu 8. Okt 2020 12:56

AW: Ausführung in sichtbarer Konsole und Inhalt der Konsole (Text) abfragen
 
Steht das Verschieben des Cursors nicht auch im Stream? z.b. als EscapeCodes ... diese müsste man dann eben entsprechend mit auswerten.



libgit2

Hatte ich vor Kurzem auch mal versucht anzufangen. (hab es aus Zeizmangel und dem enormen Umfang zurückgestellt, aber möchte irgendwann mal weitermachen)
Die Delphi-QuellCodes im GIT-Quellcode sind katastrophal veraltet und nicht mehr funktionsfähig.

Ein paar Nachteile, wenn man die libgit direkt verlinkt/einkompilert:
* einkopmpiliert: Updates lassen sich nur noch durch neukomplieren des Programms bewerkstelligen
* beim Linken gegen eine DLL ... so lange sich die genitzten Schnittstellen nicht ändern, dann ginge das schon besser

* Aufruf der Console bringt die wenigstens Funktionsprobleme/Abhängigkeiten, da sich beim GIT bekanntlich die Steuerung/Ausgaben der Console seltener ändern, als die internen APIs.
(vorallem im Linuxumfeld wird die Console häufig ferngesteuert, drum ist der Teil stabiler)

Paul Schmidt 8. Okt 2020 14:32

AW: Ausführung in sichtbarer Konsole und Inhalt der Konsole (Text) abfragen
 
@CCRDude

Das Problem ist, dass bei einem Aufruf von "push" keine Daten über die Pipe ankommen.
Also die von mir beschriebene Ausgabe, die man eigentlich in der Konsole sehen würde (der Fortschritt usw.), kommt bei einem "push" gar nicht über die Pipe an.
Bei diesen Aufruf läuft git - je nachdem wie lange der Upload dauert - im Hintergrund, ohne das ich über die Pipe irgendwelche Daten bekomme.

Bei einem "status" oder "init" oder "add" usw. kommen die Ausgaben der Konsole in der Pipe an und ich kann diese auch entsprechend mitloggen.
Aber bei einem "push" bleibt es eben komplett leer...

Hier mal der Ausschnitt, den ich verwende:
an "Callback" wird der Inhalt der Pipe übergeben. Also die jeweilige Konsolen-Ausgabe.

Delphi-Quellcode:
  saSecurity.nLength := SizeOf(TSecurityAttributes);
  saSecurity.bInheritHandle := true;
  saSecurity.lpSecurityDescriptor := nil;
  if CreatePipe(hRead, hWrite, @saSecurity, 0) then
  begin
    try
      FillChar(suiStartup, SizeOf(TStartupInfo), #0);
      suiStartup.cb := SizeOf(TStartupInfo);
      suiStartup.hStdInput := hRead;
      suiStartup.hStdOutput := hWrite;
      suiStartup.hStdError := hWrite;
      suiStartup.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
      suiStartup.wShowWindow := SW_HIDE;
      if CreateProcess(nil, PChar(ACommand + ' ' + AParameters), @saSecurity, @saSecurity, true, NORMAL_PRIORITY_CLASS, nil, nil, suiStartup, piProcess) then
        try
          repeat
            dRunning := WaitForSingleObject(piProcess.hProcess, 100);
            PeekNamedPipe(hRead, nil, 0, nil, @dAvailable, nil);
            if (dAvailable > 0) then
              repeat
                dRead := 0;
                ReadFile(hRead, pBuffer[0], CReadBuffer, dRead, nil);
                pBuffer[dRead] := #0;
                OemToCharA(pBuffer, dBuffer);

                if Assigned(CallBack) then
                begin
                  pOutput := string(dBuffer);
                  CallBack(dBuffer);
                end;
              until (dRead < CReadBuffer);
            Application.ProcessMessages;
          until (dRunning <> WAIT_TIMEOUT);

          GetExitCodeProcess(piProcess.hProcess, exitcode);
        finally
          CloseHandle(piProcess.hProcess);
          CloseHandle(piProcess.hThread);
        end;
    finally
      CloseHandle(hRead);
      CloseHandle(hWrite);
    end;
  end;

Delphi.Narium 8. Okt 2020 14:38

AW: Ausführung in sichtbarer Konsole und Inhalt der Konsole (Text) abfragen
 
Naja, formulieren wir es mal so:

Wenn ein Konsolenprogramm für die Ausgabe nicht StdOut nutzt, bekommt man die Ausgabe nicht.

Bei einer Umleitung der Ausgabe (auf der Kommandozeile) in eine Datei, wirst Du (vermutlich) auch keine Ausgabe bekommen.

Paul Schmidt 8. Okt 2020 14:47

AW: Ausführung in sichtbarer Konsole und Inhalt der Konsole (Text) abfragen
 
Zitat:

Bei einer Umleitung der Ausgabe (auf der Kommandozeile) in eine Datei, wirst Du (vermutlich) auch keine Ausgabe bekommen.
Stimmt! Das ist in Falle von "push" ebenfalls leer.

Das ist natürlich blöd!

Komme ich irgendwie auf anderen Wege an den Inhalt der Konsole, wenn ich createProcess mit "SW_SHOWNORMAL" ausführe?

Delphi.Narium 8. Okt 2020 14:50

AW: Ausführung in sichtbarer Konsole und Inhalt der Konsole (Text) abfragen
 
Nein, da gehe ich nicht von aus.

Neben StdIn, StdOut, StdErr kann man auch bei Konsolenprogrammen Ein- und Ausgaben realisieren.

Die drei StdIn, StdOut, StdErr sind dazu da, Konsolenprogramme miteinander kommunizieren zu lassen. Das ist ein kann, kein muss.

Paul Schmidt 8. Okt 2020 14:53

AW: Ausführung in sichtbarer Konsole und Inhalt der Konsole (Text) abfragen
 
Schade!

Trotzdem: herzlichen Dank für Deinen Hinweis! Nun hat zumindest das Grübeln ein Ende, warum es bei diesem Aufruf nicht funktioniert.

Grüße,
Paul


Alle Zeitangaben in WEZ +1. Es ist jetzt 06:02 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz