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
call 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!