Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Externes Programm starten (https://www.delphipraxis.net/187806-externes-programm-starten.html)

Willie1 5. Jan 2016 16:00

Externes Programm starten
 
Hallo Delphifreunde/nnen,
ich benutze diese Routine, um ein externes Programm zu starten
Delphi-Quellcode:
function TMainForm.ExecAndWait(const CommandLine, Parameter: string) : Boolean;
var
  StartupInfo: Windows.TStartupInfo;       // start-up info passed to process
  ProcessInfo: Windows.TProcessInformation; // info about the process
  ProcessExitCode: Windows.DWord;          // process's exit code
begin
  // Set default error result
  Result := False;
  // Initialise startup info structure to 0, and record length
  FillChar(StartupInfo, SizeOf(StartupInfo), 0);
  StartupInfo.cb := SizeOf(StartupInfo);
  StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
  StartupInfo.wShowWindow:=SW_HIDE;
  // Execute application commandline
  if Windows.CreateProcess(nil,
                           PChar(CommandLine),
                           nil,
                           nil,
                           False,
                           0,
                           nil,
                           PChar(Parameter),
                           StartupInfo,
                           ProcessInfo) then
  begin
    try
      // Now wait for application to complete
      if Windows.WaitForSingleObject(ProcessInfo.hProcess, INFINITE)
        = WAIT_OBJECT_0 then
        // It's completed - get its exit code
        if Windows.GetExitCodeProcess(ProcessInfo.hProcess,
          ProcessExitCode) then
          // Check exit code is zero => successful completion
          if ProcessExitCode = 0 then
            Result := True
    finally
      // Tidy up
      Windows.CloseHandle(ProcessInfo.hProcess);
      Windows.CloseHandle(ProcessInfo.hThread);
    end
  end
  else
    Showmessage(Format('Fehler:%d - %s!',[GetLastError,SysErrorMessage(GetLastError)]))
end; {TMainForm.ExecAndWait} //stammt aus Delphipraxis
Unter Vista 32-Bit klappt das Starten von Windows-Paint prima unter Windows 10-64-Bit stürzt das gesammte Programm total ab. Als Hobby-Programmierer fehlen mir Grundlagen. Kann ein 64-Bit Programm (Windows-Paint ist doch 64-Bit?) aus einem 32-Bit Programm überhaupt starten? Wenn ja, wie? Durch meine Augenerkrankung ist die Suche im Web für mich sehr schwierig, deshalb wende ich mich direkt an euch.
Danke für eure Hilfe
Willie.

hathor 5. Jan 2016 16:59

AW: Externes Programm starten
 
Warum nicht einfach so:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
ShellExecute(0,'Open','msPaint.exe', '','',SW_SHOWNORMAL);
end;
Mehr Infos:
http://delphidabbler.com/tips/134

Der schöne Günther 5. Jan 2016 17:12

AW: Externes Programm starten
 
Hallo- Wie äußert sich denn genau das "stürzt total ab"? Entweder stehe ich auf dem Schlauch, oder das sieht eigentlich richtig aus.

Kannst du mal typischer Werte für deine Parameter "CommandLine" und "Parameter" liefern?

Willie1 5. Jan 2016 17:25

AW: Externes Programm starten
 
Hallo

ExecAndWait(Format('"%s" "%s"',[ProgName,Dateina]),ExtractFilePath(Dateina))

ProgName ist Paint.exe
Dateina ist der Name der Bilddatei
Pfad wo sich das Bild befindet.

Ich habe es gerade nochmal ausprobiert, das Programm friert ein Keine Rückmeldung

Mit dem Programm ExifTools.exe, das ich ebenfalls mit ExecAndWait aufrufe klappt es.

Willie

himitsu 5. Jan 2016 17:43

AW: Externes Programm starten
 
Zitat:

Zitat von Willie1 (Beitrag 1326085)
Ich habe es gerade nochmal ausprobiert, das Programm friert ein Keine Rückmeldung

Und was sagt der Debugger, wo es hängt?

WaitForSingleObject? :roll:

Und was passiert, wenn du Paint wieder beendest?

nahpets 5. Jan 2016 17:47

AW: Externes Programm starten
 
Hallo,

mal meine unkoordinierten Spekulationen:

Heißt das Programm Paint.exe oder MSPaint.exe?

Unter Windows XP heißt es MSPaint.exe. Wurde es zwischenzeitlich umbenannt?

Wenn nein, dann bitte den Namen mal im Aufruf ändern.

Wenn man MSPaint.exe mit Parameter startet, so muss der Parameter den Namen der Bilddatei mit Pfad enthalten, also ein Parameter, der "beides" enthält.

Du übergibst aber zwei Werte. MSPaint gibt, wenn es die angegebene Datei nicht findet, eine Meldung aus (Messagebox) und beendet sich nach dem Wegklicken dieser Messagebox.

Möchte jetzt mal nicht ausschließen, dass das noch "innerhalb" des Createprocesses passiert, Du also quasi eine nicht sichtbare Messagebox wegklicken müsstest.

Ändere doch den Aufruf mal in diese Form:
Delphi-Quellcode:
ExecAndWait(Format('"%s"',[ProgName]),Format('"%s"',[Dateina]))

Eventuell könnte aber auch das funktionieren:
Delphi-Quellcode:
ExecAndWait(Format('"%s" "%s"',[ProgName,Dateina]),'')

ringli 5. Jan 2016 17:51

AW: Externes Programm starten
 
Zitat:

ExecAndWait(Format('"%s" "%s"',[ProgName,Dateina]),ExtractFilePath(Dateina))
Müsste das nicht eher so aussehen:

Delphi-Quellcode:
ExecAndWait(ProgName,Dateina)

himitsu 5. Jan 2016 18:01

AW: Externes Programm starten
 
Zu den letzten beiden Postern: Stimmt, hier ist so Einiges falsch.

Der Parameter Parameter ist in Wirklichkeit das Verzeichnis, aber das kann man ja selber nachlesen, also vorallem die ersten beiden Parameter und lpCurrentDirectory.
MSDN-Library durchsuchenCreateProcess

Willie1 5. Jan 2016 18:15

AW: Externes Programm starten
 
Hallo Leute,
ihr habt recht, ich muss da noch einiges überprüfen! Das Prpgramm heißtMSPaint.exe, habe mich verschrieben. Ich darf nur darauf hinweisen, das Programm läuft unter Vista.
Mit den Parametern stimmt was nicht, ich melde mich wieder!
Willie.

nahpets 5. Jan 2016 18:34

AW: Externes Programm starten
 
Zitat:

Zitat von ringli (Beitrag 1326089)
Zitat:

ExecAndWait(Format('"%s" "%s"',[ProgName,Dateina]),ExtractFilePath(Dateina))
Müsste das nicht eher so aussehen:

Delphi-Quellcode:
ExecAndWait(ProgName,Dateina)

Sofern Dateina Leerzeichen enthält, könnte Dateina vom aufgerufenen Programm wie mehrere Parameter interpretiert werden.

Wenn man MSPaint.exe aufruft, wird dies (vermutlich) über den Pfad (oder sonstwie) gefunden. Ruft man aber ein Programm über vollständigen Pfad und Dateinamen auf und die enthalten Leerzeichen, könnte das auch zu Fehlern führen.

Hab' nochmal in die Windows.pas geschaut, danach würd' ich mich für diese Variante entscheiden:
Delphi-Quellcode:
ExecAndWait(Format('"%s" "%s"',[ProgName,Dateina]),'')

notAssertor 6. Jan 2016 00:16

AW: Externes Programm starten
 
Ich kaufe ein Komma für's Format() in ExecAndWait().

jaenicke 6. Jan 2016 07:44

AW: Externes Programm starten
 
Das Problem ist, dass der zweite Parameter an CreateProcess variabel sein muss. Das ist er hier durch den simplen Cast
Delphi-Quellcode:
PChar(CommandLine)
nicht.

Man muss vorher UniqueString oder eine lokale Variable benutzen oder auch
Delphi-Quellcode:
PChar(CommandLine + '')
sollte reichen. Das bewirkt, dass ein neuer String erzeugt wird, der auch beschreibbar ist.

Siehe Doku:
https://msdn.microsoft.com/en-us/lib...or=-2147217396
Der Parameter ist als in und out markiert.

DeddyH 6. Jan 2016 08:37

AW: Externes Programm starten
 
Nur mal so: http://www.delphipraxis.net/6296-war...teprocess.html

Willie1 7. Jan 2016 10:36

AW: Externes Programm starten
 
Hallo Leute,
ich habe es überprüft, es ist richtig.

Programname = "MSPaint.exe" mit Pfad (C:\Windows\System32\mspaint.exe) und Bilddateiname ohne Pfad bilden die Komandozeile und der Pfad der Bilddatei den Parameter. Wie ich schonmal geschrieben habe, läuft es unter Vista prima, also kann es doch nicht am meinen "Programmierkünsten" liegen. MSPaint liegt im Ordner System32, ist also 32-Bit Programm?!.
Hat sich der Aufruf von MSPaint mit Parameter geändert?

Jaenicke und DeddyH, wollt ihr sagen, dass sich hier zwischen Vista und Windows 10 hier etwas geändert hat? Das werde ich mir vornehmen und dann wieder melden.


Ich habe es so geändert:

function TMainForm.ExecAndWait(const CommandLine, Parameter: string) : Boolean;
var
PParameter: PChar;
StartupInfo: Windows.TStartupInfo; // start-up info passed to process
ProcessInfo: Windows.TProcessInformation; // info about the process
ProcessExitCode: Windows.DWord; // process's exit code
begin
// Set default error result
PParameter:=PChar(Parameter);
Result := False;
// Initialise startup info structure to 0, and record length
FillChar(StartupInfo, SizeOf(StartupInfo), 0);
StartupInfo.cb := SizeOf(StartupInfo);
StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
StartupInfo.wShowWindow:=SW_HIDE;
// Execute application commandline
if Windows.CreateProcess(nil,
PChar(CommandLine),
nil,
nil,
False,
0,
nil,
PParameter,
StartupInfo,
ProcessInfo) then
begin
try
// Now wait for application to complete
if Windows.WaitForSingleObject(ProcessInfo.hProcess, INFINITE)
= WAIT_OBJECT_0 then
// It's completed - get its exit code
if Windows.GetExitCodeProcess(ProcessInfo.hProcess,
ProcessExitCode) then
// Check exit code is zero => successful completion
if ProcessExitCode = 0 then
Result := True
finally
// Tidy up
Windows.CloseHandle(ProcessInfo.hProcess);
Windows.CloseHandle(ProcessInfo.hThread);
end
end
else
Showmessage(Format('Fehler:%d - %s!',[GetLastError,SysErrorMessage(GetLastError)]))
end; {TMainForm.ExecAndWait}

Es hilft nicht.

Willie.

DeddyH 7. Jan 2016 10:42

AW: Externes Programm starten
 
Wenn es richtig ist, klappt ja auch alles. Ach, klappt nicht? Dann kann es auch nicht richtig sein. Setz doch einfach mal ein paar der (guten) Vorschläge in diesem Thread um.

jaenicke 7. Jan 2016 12:57

AW: Externes Programm starten
 
Zitat:

Zitat von Willie1 (Beitrag 1326257)
[B]Jaenicke und DeddyH, wollt ihr sagen, dass sich hier zwischen Vista und Windows 10 hier etwas geändert hat?

Nicht direkt, aber bei 32-Bit kommst du damit durch, dass du einen reinen in Parameter an einen in/out Parameter übergibst, bei einem 64-Bit Programm nicht.
Das Problem gab es auch schon bei Vista mit einem 64-Bit Programm. Und vermutlich auch bei XP, aber das haben nicht so viele als 64-Bit benutzt.

Willie1 7. Jan 2016 17:11

AW: Externes Programm starten
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo DeddyH, hab' ich gemacht. Es funktioniert nicht.
Anbei ExecAndWait, herausextrahiert aus dem Projekt.

Willie.

jaenicke 7. Jan 2016 17:54

AW: Externes Programm starten
 
Wenn ich
Delphi-Quellcode:
PChar(CommandLine + '')
benutze, gibt es keinen Fehler mehr. Den hattest du bei dir gar nicht, das ist mir gerade aufgefallen, weil du Delphi 2005 hast. Der tritt nur bei Unicode auf.

Jedenfalls ist das Problem schlicht, dass mspaint gar nicht sichtbar gestartet wird. Deshalb wartet dein Programm nach dem CreateProcess logischerweise unendlich, denn genau das soll der Befehl ja auch machen. Du kannst den neuen Prozess ja auch nicht sehen und beendest ihn daher nicht. Wenn du das gleich am Anfang gesagt hättest, wäre es einfacher gewesen. ;-)

Jedenfalls ist die Ursache sehr einfach. Du gibst ja den expliziten Befehl, dass Paint versteckt gestartet werden soll:
Delphi-Quellcode:
  StartupInfo.wShowWindow:=SW_HIDE;
//SW_HIDE, also versteckt starten
Probiere es mal mit SW_SHOWNORMAL.

Willie1 8. Jan 2016 18:07

AW: Externes Programm starten
 
Hallo Jaenicke,
Das ist die Lösung SW_SHOWNORMAL !!! Jetzt öffnet sich MSPaint. Klasse.
Ist klar ExifTools ist ein Konsolenprogramm, deshalb hat es im Hintergrund seine Arbeit getan.

Es bleibt nur die Frage, warum bei Vista immer MSPaint aufging auch mit SW_HIDE?

Schönen Abend und euch Allen Dank für eure Geduld
Willie.


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