Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Programm extern ausführen (https://www.delphipraxis.net/83839-programm-extern-ausfuehren.html)

Ari 7. Jan 2007 01:18


Programm extern ausführen
 
Hallo erstmal :hi:

ich hoff ich bin in der richtigen Kategorie gelandet..

Ich möchte gern mit Delphi ein Programm ausführen und die Befehle angeben, nach stundenlangem Ggoglen hab ich herausgefunden, dass ShellExecute, WinExecute und TProcess geeignet wären, wobei glaube ich nur letztere Funktion auch Befehle ausführt - oder?

Dabei hab ich jetzt folgendes Problem: Muss ja eingeben
uses SysUtils, Classes, Process;

Dann spuckt Delphi mir aus "File not found: 'Process.dcu'" - ich verzweifelt nach dieser Datei gesucht aber ich find die nicht...

Wo bekomm ich die denn jetzt her?

Sorry, kenne mich kaum mit Delphi aus und probiere jetzt schon ziemlich lange, das zum Laufen zu kriegen. Wäre nett, wenn mir jemand hilft!

Liebe Grüße,
Ariane

Harry M. 7. Jan 2007 01:24

Re: Programm extern ausführen
 
Hallo und willkomen in der Dp!

Möglichkeiten zum starten von Programmen gibt es viele. ShellExecute, WinExec oder CreateProcess und sicher noch einige mehr. Aber für Dich sich die beiden ersten interessant. bei Shellexecute musst Du die ShellApi einbinden, bei Winexec, Windows oder SysUtils. Bin mit jetzt nicht sicher.

lbccaleb 7. Jan 2007 01:35

Re: Programm extern ausführen
 
Delphi-Quellcode:
function WinExecAndWait_32(FileName: string; Visibility: Integer; bWait: Boolean = False): Longword;
var { by Pat Ritchey }
  zAppName: array[0..512] of Char;
  zCurDir: array[0..255] of Char;
  WorkDir: string;
  StartupInfo: TStartupInfo;
  ProcessInfo: TProcessInformation;
begin
  StrPCopy(zAppName, FileName);
  GetDir(0, WorkDir);
  StrPCopy(zCurDir, WorkDir);
  FillChar(StartupInfo, SizeOf(StartupInfo), #0);
  StartupInfo.cb := SizeOf(StartupInfo);
  StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
  StartupInfo.wShowWindow := Visibility;
  if not CreateProcess(nil,
    zAppName, // pointer to command line string
    nil, // pointer to process security attributes
    nil, // pointer to thread security attributes
    False, // handle inheritance flag
    CREATE_NEW_CONSOLE or // creation flags
    NORMAL_PRIORITY_CLASS,
    nil, //pointer to new environment block
    nil, // pointer to current directory name
    StartupInfo, // pointer to STARTUPINFO
    ProcessInfo) // pointer to PROCESS_INF
    then Result := WAIT_FAILED
  else
  begin
    if bWait then
      WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
    GetExitCodeProcess(ProcessInfo.hProcess, Result);
    CloseHandle(ProcessInfo.hProcess);
    CloseHandle(ProcessInfo.hThread);
  end;
end; { WinExecAndWait32 }

das ist die funktion die ich immer verwende, und die ist auch kompatibel mit späteren windows versionen!!!
um sie zu verwenden musst du unter uses windows einbinden

aufrufen kannst du die function so:

WinExecAndWait_32('c:\sin.exe +set game 2015', 1, False);

wäre eine version mit parameter


WinExecAndWait_32('c:\sin.exe', 1, False);

und diese wäre ohne parameter!!



die 1 steht für die sichtbarkeit des gestarten programms
und true/false steht bei der function für das warten auf das gestartete programm

Ari 7. Jan 2007 01:48

Re: Programm extern ausführen
 
Erstmal danke für die Hilfe!!

Kann mit beiden Varianten das gewünschte Programm starten - aber wie lasse ich Delphi die Befehle in das Programm eingeben? Möchte, dass das Programm, sobald es gestartet wurde, immer das Selbe tut - also auch immer die selben Befehle bekommt.

edit: Mir ist auch nicht so klar, was der Parameter auslöst..
edit2: ach doch, zumindest hab ich herausgefunden, dass der Parameter sich auf die Konfigurationen bezieht (wie lbccaleb ja auch mit "set" geschrieben hat, sorry..)

Harry M. 7. Jan 2007 01:58

Re: Programm extern ausführen
 
...mal andersrum gefragt: Was soll am Ende dabei rauskommen wenn "Delphi Befehle in Dein Programm eingegeben" hat?

lbccaleb 7. Jan 2007 01:58

Re: Programm extern ausführen
 
also den bsp mit dem parameter hab ich nur mal mit gepostet damit auch klar wird wie ein programm mit parametern über diese function gestartet wird, das brauchst du bei dir nicht mit eingeben wenn du keine parameter hast, desweiteren musst du natürlich die sin.exe durch dein programm austauschen, wie meinst du das mit von delphi eingeben lassen und es soll immer das selbe tun??

Ari 7. Jan 2007 02:07

Re: Programm extern ausführen
 
Ok, konkretes Beispiel:

Programm: ampl.exe
Befehle, die ich eingeben möchte: model test.mod;
(noch weitere Befehle)
quit;

Es wäre doch bestimmt möglich, dass Delphi diese Befehle direkt an das Programm weiter gibt, oder?

Am Ende soll Folgendes herauskommen:
Beispiel: Ich möchte ein Problem mit einem Programm (SCIP) lösen. Die Informationen dazu lese ich aus Edit-Fenstern ein und speichere sie in einer externen Datei (das hab ich schon irgendwie hinbekommen, funktioniert soweit).

Dann möchte ich das Lösungsprogramm starten. Dem Programm sollen die Befehle zum Lösen des Problems gegeben werden (das Programm nutzt, um die Lösung zu ermitteln, die externe Datei).

Am Ende spuckt mir das Programm eine Lösung aus, die ich dann (aber erst später, erstmal sollte ich das Ausführen hinbekommen xD) wieder *äh* "einlesen" möchte, sodass sie in den Labels meines Programms erscheinen..

Harry M. 7. Jan 2007 02:15

Re: Programm extern ausführen
 
Also Du hat (D)eine Anwendung wo du Infos in Edits hast. Jetzt soll beim Speichern gleich ein anderes programm gestarted werden, (SCIP.exe) wobei "model test.mod" an SCIP.exe übergeben wird. Richtig!?

Ari 7. Jan 2007 02:17

Re: Programm extern ausführen
 
Ja genau. Ich möchte *nachzähl* 3 Befehle an scip.exe übergeben.

Harry M. 7. Jan 2007 02:37

Re: Programm extern ausführen
 
Delphi-Quellcode:
sFileName := 'c:\path\bla.exe'
shellexecute(Handle, ExtractFileName(sFileName), 'model testy.mod', ÊxtractfilePtah(sFileName), SW_SHOW);

lbccaleb 7. Jan 2007 02:43

Re: Programm extern ausführen
 
ja das wären dann in dem fall wie ich oben beschrieben hab die parameter was ich meinte....


das wäre mit der funktion dann so:

Delphi-Quellcode:
WinExecAndWait_32('c:\path\bla.exe model testy.mod', 1, False);

Ari 7. Jan 2007 03:05

Re: Programm extern ausführen
 
Hmm er spuckt mir "Undeclared Identifier: sFileName" aus...Soll ich das noch irgendwo in die Variablen reinschreiben?

Sorry, wie gesagt, kenn mich da nicht so wirklich aus..

Was dies hier angeht
Delphi-Quellcode:
WinExecAndWait_32('c:\path\bla.exe model testy.mod', 1, False);
wird das Programmfenster sofort geschlossen. hab mal mit nem Screenshot versucht herauszufinden, was das Programm ausgibt, ich meine, dass es die Worte einzeln betrachtet oder so..
"invalid parameter: ..."

Harry M. 7. Jan 2007 03:09

Re: Programm extern ausführen
 
sFileName ist ein Sring den Du noch deklarieren musst.

Ari 7. Jan 2007 03:18

Re: Programm extern ausführen
 
Merkwürdig, habe jetzt:

Delphi-Quellcode:
procedure TForm1.BitBtn3Click(Sender: TObject);
var sFileName: String;
begin
sFileName := 'scip.exe'
shellexecute(Handle, ExtractFileName(sFileName), 'model test.mod', ExtractfilePath(sFileName), SW_SHOW);
end;
und dann wird gemeldet: "Missing operator or semicolon" und "Incompatible types: 'String' and 'PAnsiChar'".

lbccaleb 7. Jan 2007 03:31

Re: Programm extern ausführen
 
Zitat:

Zitat von Ari
Merkwürdig, habe jetzt:

Delphi-Quellcode:
procedure TForm1.BitBtn3Click(Sender: TObject);
var sFileName: String;
begin
sFileName := 'scip.exe'
shellexecute(Handle, ExtractFileName(sFileName), 'model test.mod', ExtractfilePath(sFileName), SW_SHOW);
end;
und dann wird gemeldet: "Missing operator or semicolon" und "Incompatible types: 'String' and 'PAnsiChar'".

muss so aussehen:
Delphi-Quellcode:
sFileName := 'scip.exe';
shellexecute(Handle, pchar(ExtractFileName(sFileName)), pchar('model test.mod'), pchar(ExtractfilePath(sFileName)), SW_SHOW);

Harry M. 7. Jan 2007 04:04

Re: Programm extern ausführen
 
Delphi-Quellcode:
var sFileName: Char;
würde auch gehn.

lbccaleb 7. Jan 2007 04:15

Re: Programm extern ausführen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von Harry M.
Delphi-Quellcode:
var sFileName: Char;
würde auch gehn.



sorry muss dir leider sagen nee würds nicht, denn wenn man die var als char deklariert, kann man danach ihr keinen string zuweisen, das sind inkompatible komponenten! ausserdem würde in der prozedure shellexecute dadurch gleich 2 fehler entstehen, zumeinen weil der string 'model test.mod' weiterhinn besteht und zum anderen würde es glaub ich auch noch ne meldung geben das char und pchar inkompatibel sind (da will ich mich aber nicht drauf festlegen, müsst ich selber probieren erst)


habs dir mal gemacht stellst dir das ungefähr so vor??

Harry M. 7. Jan 2007 04:20

Re: Programm extern ausführen
 
Upps Ich meinte PChar.
Aber ich muss korigieren. Du hast. Hab es eben probiert.

Ari 7. Jan 2007 17:02

Re: Programm extern ausführen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo nochmal, tut mir leid, dass ich erst jetzt wieder reinschau...

also, an und für cih funktioniert die Ausführung des Programms jetzt. Da sich das Fenster immer selbst schließt, hab ich mal probeweise das Programm mit cmd ausgeführt. Es funktioniert, wenn ich nur "scip.exe" eingebe und dann erst die Befehle eingebe. Gebe ich aber "scip.exe model xy.mod" ein, wird angezeigt "Invalid Parameter". Ist es möglich, dass Delphi dann erst das Programm scip.exe ausführt und dann die Befehle weiter gibt? Blödes Programm :(

edit: Im Anhang ist jetzt ein Bild von dem, was dann angezeigt wird...

Harry M. 7. Jan 2007 18:15

Re: Programm extern ausführen
 
Check mal mal scip.exe "model test.mod"

Wo ist das der Parameter "model" (im Screen)??

lbccaleb 7. Jan 2007 18:38

Re: Programm extern ausführen
 
ja ich wusste ja bisher nicht genau was du vorhast, jetzt wo du den screener gepostet hast kann ich dir schon mal sagen das "model" in dieser art dadrinne schon mal blödsinn ist, denn das prog erkennt diesen parameter so nicht, versuchs einfach mal ohne also so:


Delphi-Quellcode:
"scip.exe xy.mod"
dann kannst ja noch mal schreiben..

Ari 7. Jan 2007 18:44

Re: Programm extern ausführen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Funktioniert leider auch nicht. Habe außerdem leider auch die Befehle von AMPL und SCIP durchnander gebracht :oops: Kann die ja zum Glück leicht ändern..im Anhang jetzt der Versuch mit
scip.exe "read prog.zpl"

Also mit diesen Eingaben funktionierts leider nicht. Gebe ich aber zuerst scip.exe ein, lande ich im "SCIP>" und dann funktioniert "read prog.zpl"...

Ohne das "read" bzw. "model"/wie auch immer wird auch wieder angezeigt "invalid parameter <prog.zpl>"

Harry M. 7. Jan 2007 18:49

Re: Programm extern ausführen
 
Ist klar weil das programm nur die angegeben Parameter unterstützt, Die wären etwa -c -b -l
weder "read" noch "model" wird das Programm nie erkennen.

Ari 7. Jan 2007 19:38

Re: Programm extern ausführen
 
Oh mist :angel2:

Mit
Delphi-Quellcode:
WinExecAndWait_32('scip.exe -c "read sudoku.zpl opt disp sol"', 1, False);
funktionierts jetzt...

Vielen Dank an euch beide!! Hab mich ja selten doof angestellt xD

Jetzt bleibt nur noch aus, wie ich die Zeilen, die das Programm ausgibt (die Lösungen) in Delphi einlese..soll ich dazu einen extra Thread erstellen?
Könntet ihr mir da bitte auch noch helfen?

Harry M. 7. Jan 2007 20:42

Re: Programm extern ausführen
 
TDosCommand, CaptureCmd

Ari 8. Jan 2007 00:16

Re: Programm extern ausführen
 
Hab jetzt versucht, TDoscommand.pas zu installieren, da wird aber dann angezeigt
"Could not create '(mein Verzeichnispfad von Delphi)\projects\bpl\dclusr70.bpl'"
Wobei meine bpl Dateien glaub ich alle in (Delphi-Pfad)\Bin liegen..
Daraufhin hab ich ein neues Package erstellt und absolutes Chaos angerichtet..
Hab immerhin gute zwei Stunden gebraucht, um den angerichteten Schaden wieder zu reparieren bzw. herauszufinden wie ich auch wieder Dateien kompilieren kann :?

Kann mir jemand bitte helfen? Ich krieg das nicht auf die Reihe :-/

Harry M. 8. Jan 2007 04:58

Re: Programm extern ausführen
 
Morgen

Ich glaub Du hast Dein Delphi leicht verbogen. Versuch mal reparieren von Setup.

Delphi-Quellcode:
function GetConsoleOutput(const Command: String; var Output, Errors: TStringList): Boolean;
var
  StartupInfo: TStartupInfo;
  ProcessInfo: TProcessInformation;
  SecurityAttr: TSecurityAttributes;
  PipeOutputRead: THandle;
  PipeOutputWrite: THandle;
  PipeErrorsRead: THandle;
  PipeErrorsWrite: THandle;
  Succeed: Boolean;
  Buffer: array [0..255] of Char;
  NumberOfBytesRead: DWORD;
  Stream: TMemoryStream;
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;

  //Pipes erzeugen
  CreatePipe(PipeOutputRead, PipeOutputWrite, @SecurityAttr, 0);
  CreatePipe(PipeErrorsRead, PipeErrorsWrite, @SecurityAttr, 0);

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

  if CreateProcess(nil, PChar(command), nil, nil, true,
  CREATE_DEFAULT_ERROR_MODE or CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil, nil,
  StartupInfo, ProcessInfo) then begin
    result:=true;
    //Write-Pipes schließen
    CloseHandle(PipeOutputWrite);
    CloseHandle(PipeErrorsWrite);

    //Ausgabe Read-Pipe auslesen
    Stream := TMemoryStream.Create;
    try
      while true do begin
        succeed := ReadFile(PipeOutputRead, Buffer, 255, NumberOfBytesRead, nil);
        if not succeed then break;
        Stream.Write(Buffer, NumberOfBytesRead);
      end;
      Stream.Position := 0;
      Output.LoadFromStream(Stream);
    finally
      Stream.Free;
    end;
    CloseHandle(PipeOutputRead);

    //Fehler Read-Pipe auslesen
    Stream := TMemoryStream.Create;
    try
      while true do begin
        succeed := ReadFile(PipeErrorsRead, Buffer, 255, NumberOfBytesRead, nil);
        if not succeed then break;
        Stream.Write(Buffer, NumberOfBytesRead);
      end;
      Stream.Position := 0;
      Errors.LoadFromStream(Stream);
    finally
      Stream.Free;
    end;
    CloseHandle(PipeErrorsRead);

    WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
    CloseHandle(ProcessInfo.hProcess);
  end
  else begin
    result:=false;
    CloseHandle(PipeOutputRead);
    CloseHandle(PipeOutputWrite);
    CloseHandle(PipeErrorsRead);
    CloseHandle(PipeErrorsWrite);
  end;
end;


procedure TForm1.Button1Click(Sender: TObject);
var
  output, errors: TStringList;
begin
   output:=TStringList.Create;
   try
   errors:=TStringList.Create;
   if GetConsoleOutput('cmd /K '+Edit1.Text, output, errors) then
   Memo1.Lines.AddStrings(output);
   finally
   output.free;
   errors.free;
   end;

end;
Edit1.Text -> Ist Dein Command! 'Cmd /k' musst du lassen. das sich die Console sonst nicht wiederbeendet. Schau in die Hilfe wegen dem Command (Cmd /?)

Ari 8. Jan 2007 18:34

Re: Programm extern ausführen
 
Danke für die Antwort!!

Mittlerweile scheint Delphi wieder zu funktionieren, hab einfach mal reparieren lassen und meine "environment" paths zurückgesetzt, immerhin hab ich jetzt keinen fehler mit "can't find system.pas" mehr.

Delphi startet das Programm ohne Fehlermeldungen. Führe ich aber den Prozess aus (klicke also auf den Button), läuft das Programm - spuckt aber nichts aus und stürzt ab (habs auch mal mehrere Minuten laufen lassen, hat nichts gebracht). Ist es außerdem möglich, statt in ein Memo-Feld eine Zeile bzw. einen Teil einer Zeile in ein Label einzulesen?
An dem Programm kann es eigentlich auch nicht liegen, hab ein paar Befehle gekürzt, damit das SCIP-Fenster nicht zu viele Zeilen hat, bewirkte aber auch nichts. Woran kann das jetzt liegen?

edit: hab die anderen Ausführ-Befehle wie WinExecute und so gelöscht und Edit1.Text durch 'scip.exe "r prog.zpl opt disp sol"', also meine Befehle ersetzt - richtig? Hab auch WinExecute nochmal vorher ausführen lassen aber dasselbe Ergebnis.

lbccaleb 8. Jan 2007 19:32

Re: Programm extern ausführen
 
du könntest so eine zeile aus einem memo in ein label einlesen:
Delphi-Quellcode:
label1.Caption := memo1.Lines.Strings[4];
wobei die 4 die zeile im memo ist, die du auslesen möchtest...

Ari 8. Jan 2007 23:17

Re: Programm extern ausführen
 
Oh man...mein Fehler war, dass ich für SCIP nicht den Befehl "quit" eingegeben habe -.-

Hmm jetzt verbleibt zuletzt (dann hör ich auch auf zu nerven ;) ), dass ich nur einen Teil der Zeile einlese, da meine Zeilen so aussehen:
x#1#1#5
und ich will nur die 5 einlesen lassen und in das label bringen. Geht das?

lbccaleb 8. Jan 2007 23:49

Re: Programm extern ausführen
 
versuchs mal damit:


Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  output, errors: TStringList;
begin
   output := TStringList.Create;
   try
     errors:=TStringList.Create;
     if GetConsoleOutput('cmd /K '+Edit1.Text, output, errors) then
       label1.caption := output.ValueFromIndex[5];
   finally
     output.free;
     errors.free;
   end;
end;

Ari 8. Jan 2007 23:56

Re: Programm extern ausführen
 
Vielen vielen Dank, es funktioniert jetzt!! :bounce1:

Danke danke und nochmals danke :balloon:

Harry M. 9. Jan 2007 12:48

Re: Programm extern ausführen
 
Delphi-Quellcode:
     if GetConsoleOutput('cmd /K '+Edit1.Text, output, errors) then
       label1.caption := output.ValueFromIndex[5]
       else
       label1.caption := errors.text;
Zwecks eventueller Fehler, ne :wink:

Ari 10. Jan 2007 21:03

Re: Programm extern ausführen
 
Och mist...heut ist mir ein Fehler aufgefallen:

hatte RunCaptured('e:', 'scip.exe', '-c "read prog.zpl"') benutzt und wie erwartet funktionierte die ganze Geschichte auf einem anderen Computer wieder nicht..

Übrigens läuft das ganze über meinen USB-Stick, dachte also daran, einfach per c:\windows\explorer (müsste der arbeitsplatz sein..eigentlich o.O) meinen USB-Stick "anzusprechen" - aber der wird auch bei jedem PC anders benannt, G, Q, F, wie auch immer.

Dann hab ich nach Befehlen gesucht, die einfach auf das Verzeichnis verweisen, in dem mein Delphi-Programm selbst sich befindet, also das aktuelle Verzeichnis. "chdir" und "cd" hab ich ausprobiert aber das ging auch nicht (geht nur in cmd?)

Zuletzt wollte ich das durch eine Eingabe des Verzeichnisses in ein Edit-Fenster laufen lassen, aber dort wird angezeigt, dass der Verzeichnisname ungültig sei.

Könntet ihr mir bitte noch einmal helfen?

edit: also RunCaptured scheint nur das Laufwerk zu brauchen, nicht mal den kompletten Pfad..

edit2: achja, hier der link zu runcaptured selbst.. http://www.freelists.org/archives/sd.../msg00001.html das hab ich so eingesetzt und an sich funktionierts (aber halt nur auf meinem pc)

Olli 10. Jan 2007 21:08

Re: Programm extern ausführen
 
Wenn du die Ausgabe nicht abfangen musst, hilft auch Hier im Forum suchenShellExecuteAndWait ... (hier der Direktlink zu meinem damaligen Beitrag)

Ari 10. Jan 2007 21:14

Re: Programm extern ausführen
 
Mit Ausgabe abfangen meinst du, dass Delphi Zeilen aus dem ausgeführten Programm ausliest? Brauche das Einlesen/Abfangen leider nach wie vor..

Ari 11. Jan 2007 19:49

Re: Programm extern ausführen
 
Habs jetzt rausgefunden :) muss dafür nur
RunCaptured('.\', 'scip.exe', '-c "read prog.zpl quit"')

Nochmal danke :hi:

Dschingis 18. Jan 2007 05:26

Re: Programm extern ausführen
 
Ich bedanke mich ebenfalls. Habe beim Lesen einiges kapiert und gelernt.

Danke an alle beteiligten.

Dschingis


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:14 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