Delphi-PRAXiS
Seite 2 von 2     12   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Externes von mir gestartes Programm beenden? Hilfe! (https://www.delphipraxis.net/14388-externes-von-mir-gestartes-programm-beenden-hilfe.html)

firefighter 9. Jan 2004 08:39

Re: Externes von mir gestartes Programm beenden? Hilfe!
 
Zitat:

Zitat von choose
Zunächst einmal solltest Du Bool nicht mit Boolean sondern mit LongBool übersetzen, dann reicht es vollkommen aus, für das Ergebnis von GetWindowThreadProcessId eine lokale Variable (wo und wie ist dwPID denn deklariert?) und die delphi-typische Version ohne Pointer zu verwenden.

Ansonsten kann ich keinen Fehler entdecken, meine getestete Version sieht annähernd genauso aus und funktioniert. Vielleicht übergibst Du an CloseProcessWindows keine ProcessID sondern ein Handle auf den Prozess?
Überprüfen kannst Du das ganze mit einem Aufgruf der Form
Delphi-Quellcode:
CloseProcessWindows(GetCurrentProcessID);
mit dem eigenen Programm.

dwPID kommt noch vom CreateProcess ist eine globale Variable. Habs mal mit LongBool ersetzt und das Testprogramm (mehr ist es noch nicht) angehangen.

firefighter 9. Jan 2004 09:03

Re: Externes von mir gestartes Programm beenden? Hilfe!
 
Liste der Anhänge anzeigen (Anzahl: 1)
Soory, aber der SQL scheint ständig abzuschmieren:

phpBB : Critical Error

Also ich kann nichts dafür, daß Hai und Katze wieder Katzenhai spielen und am Netzwerkkabel rumzupfen...
hm. Der Hai streitet alles ab. Muss wohl das Kätzchen sein... :roll:

Ich versuch nochmal das Attachment

choose 9. Jan 2004 09:16

Re: Externes von mir gestartes Programm beenden? Hilfe!
 
Hallo firefighter,

ich habe mir Deinen Code einmal angesehen und konnte zwei Probleme entdecken:
  1. Null hat in Delphi im Zusammenhang mit Varianten (genauer OLE) eine besondere Bedeutung und ist nicht direkt vergleichbar mit der Konstante in C. Verwende beim Aufruf von PostMessage einfach den Aufruf
    Delphi-Quellcode:
    PostMessage(AHandle, WM_CLOSE, 0, 0);
  2. Wie bereits vermutet, rufst Du Deine Funktion nicht mit der ProcessID sondern mit dem Handle des Prozesses auf. In der OH zu CreateProcess findest Du auch eine Reference auf die von Dir verwendete Struktur TProcessInformation (dort: PROCESS_INFORMATION). Zu diesem strukturierten Datentyp ist zu lesen:
    Zitat:

    hProcess
    Returns a handle to the newly created process. [..]
    Zu GetWindowThreadProcessId steht jedoch, wie bereits erwähnt:
    Zitat:

    lpdwProcessId
    Points to a 32-bit value that receives the process identifier. [..]
    Du vergleichst demnach, wie bereits vermutet, "Äpfel mit Birnen".

firefighter 9. Jan 2004 09:27

Re: Externes von mir gestartes Programm beenden? Hilfe!
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo choose,

danke für die schnelle Antwort. Ich habe jetzt ein paar Modifikationen entsprechend Deiner Aussage getroffen und es funktioniert :) Würdest Du mir den Gefallen tun und nochmal darüber schauen, damit ich nicht noch etwas falschen geändert habe? Vielen Dank!

Gruss firefighter

choose 9. Jan 2004 09:51

Re: Externes von mir gestartes Programm beenden? Hilfe!
 
Die beiden Stellen sind in Deiner Version so geändert, dass es funktionieren sollte (habe es aber nicht getestet, Du sagtest schließlich, dass es klappt ;)).

Abschließend eine kleine Anmerkung:
Mir fällt auf, dass Deine Routinen auf globalen Variablen basieren, was nicht immer notwendig ist und in einigen Fällen sogar Probleme bereiten kann. Darüber hinaus erschwert die von Dir vorgenommene Formulierung das Erstellen einer Unit mit den gesammelten Funktionen.
Falls Du später mehrere Programme gleichzeitig starten und schließen möchtest, wird das ebenfalls nicht funktionieren, weil die Routinen von einer benannten Variablen ausgehen...
Deshalb hier eine Variante, die mit lokalen Variablen arbeitet außerdem noch eine andere hübsche Lösung für die CallBack-Funktion, bei der die CallBack-Funktion ebenfalls von außen "nicht sichtbar" ist (Funktioniert allerdings nur, weil ausschließlich lokale Variablen verwendet werden, bei anderen Lösungen also mit Bedacht einsetzen!), verwendet:
Delphi-Quellcode:
procedure CloseProcessWindows(const AProcessID: DWord);
  function CloseWindowsCB(AHandle :HWND; AProcessID: DWord): LongBool; stdcall;
  var
    myProcessID: DWord;
  begin
    GetWindowThreadProcessId(AHandle, @myProcessID);
    // compare process id of AHandle against AProcessID
    if myProcessID=AProcessID then
      PostMessage(AHandle, WM_CLOSE, 0, 0);

    Result:= True;
  end;
begin
  EnumWindows(@CloseWindowsCB, AProcessID);
end;

function RunProcess(const AFilename, AParams: string;
  AWindowState: Word; out AProcessInfo: TProcessInformation): Boolean;
const
  StartFlags = STARTF_USESHOWWINDOW;
  CreationFlags = CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS;
var
  myStartUpInfo: TStartUpInfo;
begin
  // prepare Startup Info
  ZeroMemory(@myStartUpInfo, SizeOf(myStartUpInfo));
  with myStartUpInfo do
  begin
    cb:= SizeOf(myStartUpInfo);
    dwFlags:= StartFlags;
    wShowWindow:= AWindowState;
  end;

  // create new process using
  //   cmdline - AFilename AParams
  //   currdir - Path of AFilename
  Result:= CreateProcess(nil, PChar(Format('"%s" %s', [AFilename, AParams])),
    nil, nil, False, CreationFlags, nil, PChar(ExtractFilePath(AFileName)),
    myStartUpInfo, AProcessInfo);
end;
out ist neben const und var eine weitere Form des Bei Google suchencall by reference und signalisiert, dass der ursprüngliche Wert der Variablen verworfen wird. Wann immer Du Funktionen schreibst, die so Variablen "ausgeben" aber keine Eingaben verlangen, solltest Du statt Pointern oder var dieses Schlüsselwort verwenden.

Der Aufruf könnte dann in etwa so gestalltet sein:
Delphi-Quellcode:
var
  myProcessInfo: TProcessInformation;
begin
  //..
  if RunProcess(myFilename, myParam, myProcessInfo, SW_SHOW) then
  begin
    //..
    CloseProcessWindows(myProcessInfo.dwProcessId);
Es bleibt zu überlegen, ob Du statt eines Boolean nicht einfach die ProcessID zurückgiebst und im Fehlerfall eine Exception wirfst. Dann nämlich wäre auch der Einsatz optionaler Parameter eine geeignete Vereinfachung, und die Funktion könnte in dieser vereinfachten Form verwendet werden:
Delphi-Quellcode:
try
  myProcessID:= RunProcess(myFilename); // eq (myFilename, '', SW_SHOW)
  yourProcessID:= RunProcess(yourFilename, yourParam); //eq (yourFilename, yourParam, SW_SHOW)
  anotherProcessID:= RunProcess(anotherFilename, anotherParam, SW_HIDE);
except
  on EProcessNotCreatable do
    //..
end;
Viel Erfolg!


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:25 Uhr.
Seite 2 von 2     12   

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