In my GUI app I run console app and need handle of its window. I tried with EnumWindows(), see code below, but it does not work. On list there is no my console app.
type
TEnumWindowsData = record
ProcessId: Cardinal;
WinHandle: THandle;
List: TStrings; // For test only
end;
PEnumWindowsData = ^TEnumWindowsData;
function FindWindow(hWnd: THandle; lParam: LPARAM): BOOL; stdcall;
var
ParamData: TEnumWindowsData;
ProcessId: Cardinal;
WinTitle: array[0..200] of Char; // For test only
begin
ParamData := PEnumWindowsData(lParam)^;
GetWindowThreadProcessId(hWnd, ProcessId);
if ProcessId <> ParamData.ProcessId then
Result := True
else begin
ParamData.WinHandle := hWnd;
Result := False;
end;
// For test only
GetWindowText(hWnd, WinTitle, Length(WinTitle) - 1);
ParamData.List.Add(IntToStr(ProcessId) + ' ' + IntToStr(hWnd) + ' ' + WinTitle);
end;
procedure TForm1.Button1Click(Sender: TObject);
function RunApp(const AProgram: string): Cardinal;
var
StartupInfo: TStartupInfo;
ProcessInformation: TProcessInformation;
begin
Result := 0;
...
if CreateProcess(nil, PChar(AProgram), nil, nil, False,
NORMAL_PRIORITY_CLASS, nil, nil, StartupInfo, ProcessInformation)
then
Result := ProcessInformation.dwProcessId;
...
end;
var
ParamData: TEnumWindowsData;
begin
ParamData.ProcessId := RunApp('cmd.exe /C D:\TMP\TEST.exe');
ParamData.WinHandle := 0;
ParamData.List := Memo1.Lines;
EnumWindows(@FindWindow, THandle(@ParamData));
FWindowHandle := ParamData.WinHandle;
end;
The following code simply creates the process (console application), attaches your process to the newly created console by
AttachConsolefunction and from that attached console takes the window handle using theGetConsoleWindowfunction.The biggest weakness of the following code is that
CreateProcessfunction returns immediately at the time, when the console is not yet fully initialized and when you try to attach the console immediately after, you will fail. Unfortunately, there’s noWaitForInputIdlefunctionfor console applicationsso as one possible workaround I would choose the attempt to attach the console in some limited loop count and once it succeed, get the handle and detach the console.In code that might look like follows. The
RunAppfunction there should return the handle of the console window (assuming you’ll run only console applications from it), and should wait approx. 1 second for the console application you’ve started to be attachable. You can modify this value either by changing initial value of theAttemptvariable and/or by changingSleepinterval.Then you can e.g. change the title of a console window of your lauched application this way: