AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Code-Bibliothek Neuen Beitrag zur Code-Library hinzufügen Delphi Ausgabe einer Konsolenanwendung abfangen (simple Fassung)

Ausgabe einer Konsolenanwendung abfangen (simple Fassung)

Ein Thema von stz · begonnen am 24. Aug 2008 · letzter Beitrag vom 2. Nov 2008
Antwort Antwort
Benutzerbild von stz
stz

Registriert seit: 8. Sep 2005
Ort: Neuendeich, Lübeck
277 Beiträge
 
Turbo Delphi für Win32
 
#1

Ausgabe einer Konsolenanwendung abfangen (simple Fassung)

  Alt 24. Aug 2008, 17:05
Moin moin,
mithilfe von Jens Code und diesem Delphi-Treff Tipp habe ich eine kleine Funktion geschrieben, die eine Konsolenanwendung startet, auf deren Ende wartet und die Ausgabe als String zurückliefert:

Delphi-Quellcode:
function Konsole(const Command: String): String;
var
  StartupInfo: TStartupInfo;
  ProcessInfo: TProcessInformation;
  SecurityAttr: TSecurityAttributes;
  OutputPipeRead, OutputPipeWrite: THandle;
  Res: Boolean;
  BufSize: Cardinal;
  Buffer: String;
  BytesRead: Cardinal;
begin
  //Initialisierung ProcessInfo
  FillChar(ProcessInfo, SizeOf(TProcessInformation), 0);

  //Initialisierung SecurityAttr
  FillChar(SecurityAttr, SizeOf(TSecurityAttributes), 0);
  SecurityAttr.nLength := SizeOf(SecurityAttr);
  SecurityAttr.bInheritHandle := true;
  SecurityAttr.lpSecurityDescriptor := nil;

  //Pipe erzeugen
  CreatePipe(OutputPipeRead, OutputPipeWrite, @SecurityAttr, 0);

  //Initialisierung StartupInfo
  FillChar(StartupInfo, SizeOf(TStartupInfo), 0);
  StartupInfo.cb:=SizeOf(StartupInfo);
  StartupInfo.hStdInput := 0;
  StartupInfo.hStdOutput := OutputPipeWrite;
  StartupInfo.hStdError := OutputPipeWrite;
  StartupInfo.wShowWindow := SW_HIDE;
  StartupInfo.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;

  //Prozess erzeugen
  Res := CreateProcess(nil, PChar(command), nil, nil, true,
                   CREATE_DEFAULT_ERROR_MODE or CREATE_NEW_CONSOLE or
                   NORMAL_PRIORITY_CLASS, nil, nil, StartupInfo, ProcessInfo);

  //OutputPipeWrite schließen
  CloseHandle(OutputPipeWrite);

  Result := '';

  if Res then
  begin
    //OutputPipeRead auslesen
    SetLength(Buffer, 5000);
    BufSize := Length(Buffer);
    repeat
      Res := ReadFile(OutputPipeRead, Buffer[1], BufSize, BytesRead, nil);
      Result := Result + Copy(Buffer, 1, BytesRead);
    until not Res;

    //auf Prozessende warten
    WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
    CloseHandle(ProcessInfo.hProcess);
  end;

  //OutputPipeRead schließen
  CloseHandle(OutputPipeRead);
end;
Aufruf-Beispiel:
ShowMessage(Konsole('cmd /c dir C:\')); Grüße
Malte
Malte Schmitz
Der Unterschied zwischen Theorie und Praxis ist in der Praxis größer als in der Theorie.

Entwickler des HTML-Editors MEdit (DP)
  Mit Zitat antworten Zitat
blackdrake

Registriert seit: 22. Aug 2003
Ort: Bammental
618 Beiträge
 
Delphi 10.3 Rio
 
#2

Re: Ausgabe einer Konsolenanwendung abfangen (simple Fassung

  Alt 8. Sep 2008, 00:58
Hallo.

Ich hätte mir ja gerne noch gewünscht, dass sowas auch gehen würde:

showmessage(Konsole('ver')); Anstelle das so auszudrücken:

showmessage(Konsole('cmd /c ver')); Weitere Vorschläge:
- Unter Umständen das Arbeitsverzeichnis setzen?
- Und eventuell die Suchpfade des OS berücksichtigen (sofern dies nicht bereits automatisch geschieht).
- Falls Anwendung nicht gefunden wird / kein Prozess eröffnet wird: Eine eigen definierte Exception (z.B. ECommandOrFileNotFound) auslösen. -> Kann dann mit try..except behandelt werden, wenn der Benutzer keine Meldung sehen soll.
- (Kleinigkeit Die Puffergröße 5000 in eine Konstante legen.

Was wäre denn überhaupt die komplexe Fassung, wenn das die simple Fassung ist?

Gruß
blackdrake
Daniel Marschall
  Mit Zitat antworten Zitat
Benutzerbild von stz
stz

Registriert seit: 8. Sep 2005
Ort: Neuendeich, Lübeck
277 Beiträge
 
Turbo Delphi für Win32
 
#3

Re: Ausgabe einer Konsolenanwendung abfangen (simple Fassung

  Alt 22. Sep 2008, 12:48
Zitat von blackdrake:
Ich hätte mir ja gerne noch gewünscht, dass sowas auch gehen würde:
showmessage(Konsole('ver')); Anstelle das so auszudrücken:
showmessage(Konsole('cmd /c ver'));
Moin blackdrake,
bei ver handelt es sich um keine Anwendung, sondern um einen Befehl der Windows-Shell. Da die Funktion aber eine Anwendung startet, muss man zunächst die Anwendung cmd starten, um den Befehl auszuführen. Du kannst die Funktion natürlich recht einfach abändern, indem du dem übergebenen String einfach automatisch immer ein 'cmd /c ' voransetzt.

Zitat von blackdrake:
- Und eventuell die Suchpfade des OS berücksichtigen (sofern dies nicht bereits automatisch geschieht).
Das müsste eigentlich Windows von alleine machen...

Zitat von blackdrake:
- Falls Anwendung nicht gefunden wird / kein Prozess eröffnet wird: Eine eigen definierte Exception (z.B. ECommandOrFileNotFound) auslösen.
Meiner Funktion fehlt jegliche Fehlerbehandlung, so wie ich das gerade überblicke...

Zitat von blackdrake:
Was wäre denn überhaupt die komplexe Fassung, wenn das die simple Fassung ist?
Das simple an dieser Fassung ist, dass die Funktion schlicht auf das Ende des gestarteten Prozesses wartet und die aufrufende Anwendung solange hängt. Das kann man eleganter, aber dann auch komplexer, lösen. Ein Beispiel dazu findet sich unter anderem im bereits im ersten Beitrag verlinkten Code von Jens.

Ich komme in nächster Zeit sicherlich nicht dazu, die Funktion zu optimieren - ich habe aber absolut nichts dagegen, wenn Du Dich meinem Code annimmst und ihn verbesserst.

Gruß
Malte
Malte Schmitz
Der Unterschied zwischen Theorie und Praxis ist in der Praxis größer als in der Theorie.

Entwickler des HTML-Editors MEdit (DP)
  Mit Zitat antworten Zitat
peep
(Gast)

n/a Beiträge
 
#4

Re: Ausgabe einer Konsolenanwendung abfangen (simple Fassung

  Alt 1. Nov 2008, 19:12
@#1: Funtioniert bestens (Vielen Dank!!!), aber die erste Zeile des zurückgegebenen Strings sollte bei mir so aussehen:

" Datenträger in Laufwerk T: ist T_WIN_XP"

sieht bei mir aber leider so aus:

" Datentr„ger in Laufwerk T: ist T_WIN_XP"

Weshalb kommt das "ä" (vom Wort "Datenträger") als ",," (ist wohl kein doppeltes Komma, sondern ein anderes Zeichen) hier (nur bei mir?) als Rückgabewert raus?

Was ist dieses andere Zeichen denn für eines, woher kommt es?

Ratlose Grüße
peep
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.119 Beiträge
 
Delphi 10.4 Sydney
 
#5

Re: Ausgabe einer Konsolenanwendung abfangen (simple Fassung

  Alt 1. Nov 2008, 19:14
Das liegt an der unterschiedlichen Codierung zwischen ASCII und ANSI. Abhilfe schaffen da die Funktionen OEMToChar bzw. CharToOEM.
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Benutzerbild von stz
stz

Registriert seit: 8. Sep 2005
Ort: Neuendeich, Lübeck
277 Beiträge
 
Turbo Delphi für Win32
 
#6

Re: Ausgabe einer Konsolenanwendung abfangen (simple Fassung

  Alt 1. Nov 2008, 19:16
Zitat von peep:
" Datentr„ger in Laufwerk T: ist T_WIN_XP"
Das Problem liegt an den verschiedenen Zeichensätzen von DOS und Windows. Die ersten 127 Zeichen sind in allen Zeichensätzen gleich (ASCII). Die deutschen Umlaute liegen aber leider in den zweiten 128 Zeichen und dort passen die verschiedenen Zeichensätze von DOS und Windows nicht zusammen... Wie man das Problem allgemein gültig lösen kann, weiß ich leider auch nicht. Als einfache Lösung, könnte man sich die sechs Zeichen ä, ü, ö, Ä, Ü, und Ö aus dem DOS-Zeichensatz heraussuchen und durch die entsprechenden im Windows-Zeichensatz mit Delphi-Referenz durchsuchenStringReplace ersetzen.

Grüße
Malte

Edit:

Code:
Zeichen DOS: Westeuropa  Windows: Westlich
Ä        #$8E             #$C4
Ö        #$99              #$D6
Ü        #$9A             #$DC
ä        #$84              #$E4
ö        #$94              #$F6
ü        #$81              #$FC
Hey - der rote Kasten klemmt. Muss mir OEMToChar bzw. CharToOEM mal ansehen
Malte Schmitz
Der Unterschied zwischen Theorie und Praxis ist in der Praxis größer als in der Theorie.

Entwickler des HTML-Editors MEdit (DP)
  Mit Zitat antworten Zitat
peep
(Gast)

n/a Beiträge
 
#7

Re: Ausgabe einer Konsolenanwendung abfangen (simple Fassung

  Alt 1. Nov 2008, 19:40
@DeddyH und stz:

XP und Vista sind jewils auf NTFS installiert, Delphi7 jeweils auf FAT32, die kompilierten EXE-Ausgaben von D7 werden ebenfalls auf FAT32 ausgegeben und von FAT32 aus gestartet.

Was meint ihr mit "den verschiedenen Zeichensätzen von DOS und Windows"?

Hier gibt es kein DOS mehr...

Mehr Informationen kann ich Euch leider nicht geben, da ich nicht weiß, welche zusätzlichen Infos ihr brauchen würdet

Habt ihr trotzdem noch Vorschläge für mich?

peep
  Mit Zitat antworten Zitat
Benutzerbild von stz
stz

Registriert seit: 8. Sep 2005
Ort: Neuendeich, Lübeck
277 Beiträge
 
Turbo Delphi für Win32
 
#8

Re: Ausgabe einer Konsolenanwendung abfangen (simple Fassung

  Alt 1. Nov 2008, 20:04
Zitat von peep:
Was meint ihr mit "den verschiedenen Zeichensätzen von DOS und Windows"?

Hier gibt es kein DOS mehr...
Doch
Wenn Du zum Beispiel
Konsole('cmd /c ver') aufrufst, startest Du damit die Windows-Eingabeaufforderung. Das ist zwar nicht so ganz dasselbe wie DOS, arbeitet aber auf jeden Fall mit dem Zeichensatz "DOS: Westlich".

Du musst also die Zeichen, die dir die Funktion Konsole zurückgibt, vom DOS- in den Windows-Zeichensatz umwandeln. Entweder mit DeddyHs oder meinem Vorschlag.

Grüße
Malte
Malte Schmitz
Der Unterschied zwischen Theorie und Praxis ist in der Praxis größer als in der Theorie.

Entwickler des HTML-Editors MEdit (DP)
  Mit Zitat antworten Zitat
peep
(Gast)

n/a Beiträge
 
#9

Re: Ausgabe einer Konsolenanwendung abfangen (simple Fassung

  Alt 2. Nov 2008, 04:12
Faust in die Tasche, Luft anhalten, bis Zehn zählen!

Danke nochmals für die Tipps und Tricks zur Problemlösung!

Besten Dank!
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:01 Uhr.
Powered by vBulletin® Copyright ©2000 - 2021, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf