Delphi-Version: 2010
Mit Delphi ein anderes Delphiprogramm ansprechen
Hallo ich habe bereits ein Programm geschrieben als Konsolenanwendung welches mit Parametern arbeitet. Nun würde ich gerne noch eine Oberfläche dazu programmieren.
Damit ich mir Arbeit & Zeit spare habe ich mir gedacht, dass es doch sicher eine Möglichkeit gibt mein bereits bestehendes Programm einfach mit meinem neuen Programm aufrufen könnte und die Parameter übergeben würde. Meine Frage ist jetzt wie genau ich so etwas anstelle und ob es auch möglich ist z.b Fehlermeldungen also allgemein Ausgaben aus dem Konsolenprogramm welches dann im Hintergrund laufen soll auszulesen und in der GUI wiederzugeben. |
AW: Mit Delphi ein anderes Delphiprogramm ansprechen
ShellExecute kann Programme aufrufen. Da kannst auch Parameter mit übergeben. Die können über ParamStr(x) gelesen werden
Mit Returncodes kannst Du auch fehler an den Aufrufer melden. Zum bsp mit der Procedure Halt in Delphi, die akzeptiert eine Numemr als Parameter und die kannst in einer batch datei oder in Delphi abfangen. |
AW: Mit Delphi ein anderes Delphiprogramm ansprechen
Das ist sogar nicht auf Fehlercodes beschränkt. Du kannst den kompletten Inhalt des Konsolenprogramms über Pipes auslesen:
http://stackoverflow.com/questions/2...ui-application |
AW: Mit Delphi ein anderes Delphiprogramm ansprechen
Zitat:
|
AW: Mit Delphi ein anderes Delphiprogramm ansprechen
http://msdn.microsoft.com/en-us/libr...=vs.85%29.aspx
Zitat:
|
AW: Mit Delphi ein anderes Delphiprogramm ansprechen
Und ansonsten noch alles, was mit IPC zu tun hat.
Messages, Pipes, Sockets, MMFs ........ Die bisher genannten Dinge, sind aber Möglichkeiten, die praktisch jedes Programm von Haus aus bietet, über die bekannten Standardwege. Alles Andere wird praktisch speziell "zusätzlich" in beide Programme eingebaut, damit diese sich direkt unterhalten können. |
AW: Mit Delphi ein anderes Delphiprogramm ansprechen
Hätte ich spontan auch gesagt, wenn auch keinen Code zur Hand: Ich hätte deinen "Kindprozess" mittels CreateProcess gestartet und somit gleich die stdOut-Handles auf eine Pipe, welche deine Elternanwendung aufmacht, umgebogen.
Das hier auf SO scheint exakt in diese Richtung zu gehen: http://stackoverflow.com/q/2957490/2298252 |
AW: Mit Delphi ein anderes Delphiprogramm ansprechen
Zitat:
|
AW: Mit Delphi ein anderes Delphiprogramm ansprechen
Wenn du dein Konsolenprogramm in zwei Teile splitten würdest könnst du den Teil der die eigentliche Arbeit verrichtet auch in der Anwendung mit der GUI einbinden.
Das ist einfacher und sicherer als von der GUI-Anwendung auf die Konsolenanwendung zuzugreifen. Dazu benötigst du eine Klasse in einer eigenen Unit die von beiden Programmen mit
Delphi-Quellcode:
eingebunden wird.
uses
Dieser Klasse wird über Properties alle Informationen eingespeist und dann eine "DoWork"-Methode aufgerufen. Falls während dieser Arbeit eine Rückmeldung erforderlich sein sollte, dann lässt sich dies über ein Event bewerkstelligen. Man braucht dann in der Konsolenanwendung noch eine weitere Klasse die das Event empfängt und die Info per
Delphi-Quellcode:
an die Konsole ausgibt, aber das ist halb so schlimm wie es sich anhört.
writeln
|
AW: Mit Delphi ein anderes Delphiprogramm ansprechen
Stell dir eine Pipe wie einen TFileStream vor ... allerdings nur im Lesemous, bzw nur im Schreibmodus und ohne Seek und Co. , also nur Read ORDER Write.
(drum kann man die Ein und Ausgaben auch so schön auf Dateien umleiten, wie man es z.B. aus den BAT-Dateien mit dem ">" kennt) Es gibt bei Konsolenanwendungen 3 dieser Pipes: StdIn > der Stream für die Eingabe von der Tastatur StdOut > der Stream für die Ausgabe zum Monitor (also in die Konsole) ErrOut > der Strream geht auch auf den Monirot und gibt quasi die Fehlermeldungen aus (oder irgendwie sowas) |
AW: Mit Delphi ein anderes Delphiprogramm ansprechen
http://de.wikipedia.org/wiki/Standard-Datenstr%C3%B6me
ErrOut = stderr ;) |
AW: Mit Delphi ein anderes Delphiprogramm ansprechen
Zitat:
Ich werfe es hier einfach mal hinein:
Delphi-Quellcode:
unit Unit13;
interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls; type TMainForm = class(TForm) gridpanel: TGridPanel; startButton: TButton; stopButton: TButton; stdOutMemo: TMemo; Timer1: TTimer; procedure Timer1Timer(Sender: TObject); procedure startButtonClick(Sender: TObject); procedure stopButtonClick(Sender: TObject); private const // relativer Pfad ausgehend vom Arbeitsverzeichnis childProcessApplicationName: String = '.\..\ChildProcess\Win32\Debug\ChildProcessProject.exe'; private var myProcess: TProcessorNumber; readHandle: THandle; writeHandle: THandle; private procedure startProcess(); procedure stopProcess(); procedure tryStartProcess(); procedure tryStopProcess(); procedure createMeAPipe( var readHandle: THandle; var writeHandle: THandle ); /// <exception cref="EFileNotFoundException" /> procedure checkChildPossible(); procedure tryReadFromPipe(); function isValidReadHandle(): Boolean; end; var MainForm: TMainForm; implementation {$R *.dfm} { TMainForm } procedure TMainForm.startButtonClick(Sender: TObject); begin startProcess(); end; procedure TMainForm.startProcess(); begin startButton.Enabled := False; try tryStartProcess(); stopButton.Enabled := True; except startButton.Enabled := True; raise; end; end; procedure TMainForm.stopButtonClick(Sender: TObject); begin stopProcess(); end; procedure TMainForm.stopProcess(); begin stopButton.Enabled := False; try tryStopProcess(); startButton.Enabled := True; except stopButton.Enabled := True; raise; end; end; procedure TMainForm.Timer1Timer(Sender: TObject); begin if isValidReadHandle() then tryReadFromPipe(); end; procedure TMainForm.tryReadFromPipe(); const readBufferLength = 2400; var buffer: Array[0..readBufferLength] of AnsiChar; bytesRead: DWORD; begin ReadFile(readHandle, buffer, readBufferLength, bytesRead, nil); buffer[bytesRead] := #0; stdOutMemo.Lines.Append(buffer); end; function TMainForm.isValidReadHandle(): Boolean; begin Result := not (readHandle = 0) and not (readHandle = INVALID_HANDLE_VALUE) ; end; procedure TMainForm.tryStartProcess(); var startInfo: TStartupInfo; processInfo: TProcessInformation; errorCode: Cardinal; errorMsg: String; dwCreationFlags: DWORD; cmdLine: String; applicationName: String; begin checkChildPossible(); createMeAPipe(readHandle, writeHandle); startInfo := Default(TStartupInfo); startInfo.cb := SizeOf(startInfo); startInfo.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW; startInfo.wShowWindow := SW_SHOW; // Wegen STARTF_USESTDHANDLES in den dwFlags explizit alle drei Handles setzen startInfo.hStdOutput := writeHandle; startInfo.hStdInput := GetStdHandle(STD_INPUT_HANDLE); startInfo.hStdError := GetStdHandle(STD_ERROR_HANDLE); processInfo := Default(TProcessInformation); applicationName := GetCurrentDir()+PathDelim+ childProcessApplicationName; if not CreateProcess( PWideChar(applicationName), nil, nil, // Standard-Sicherheit, Handle wird nicht vererbt nil, // Standard-Sicherheit, Handle wird nicht vererbt True, // Handles (Schreibepipe!) vererben 0, // Keine besonderen dwCreationFlags nil, nil, startInfo, processInfo ) then raise Exception.Create( 'TMainForm.tryStartProcess: Errorcode '+ GetLastError().ToString()+ ' bei CreateProcess' ) ; end; procedure TMainForm.checkChildPossible(); begin if not FileExists( GetCurrentDir()+childProcessApplicationName ) then raise EFileNotFoundException.Create( 'TMainForm.checkChildPossible: ' +'Datei ' +childProcessApplicationName.QuotedString() +' nicht gefunden. Aktuelles Arbeitsverzeichnis ist ' +GetCurrentDir().QuotedString() ); end; procedure TMainForm.createMeAPipe( var readHandle: THandle; var writeHandle: THandle ); var saSecurity: TSecurityAttributes; begin saSecurity.nLength := SizeOf(TSecurityAttributes); saSecurity.bInheritHandle := True; saSecurity.lpSecurityDescriptor := nil; if not CreatePipe(readHandle, writeHandle, @saSecurity, 0) then raise Exception.Create('TMainForm.createMeAPipe: Konnte keine Pipe erstellen'); end; procedure TMainForm.tryStopProcess; begin raise EProgrammerNotFound.Create('derp'); end; end. |
AW: Mit Delphi ein anderes Delphiprogramm ansprechen
Zitat:
|
AW: Mit Delphi ein anderes Delphiprogramm ansprechen
.. hast Du die source-codes von dem consolen Programm nicht.
Wenn ja würde ich eher die zur Hand nehmen und in das GUI-Pogramm einbinden. Grüße Klaus |
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:11 Uhr. |
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