如何启动一个应用程序,并获得与Delphi的句柄?

我想从Delphi启动一个应用程序,并获得一个句柄,所以我可以将这个应用程序的主窗口embedded到TFrametypes的框架中。 到目前为止我已经尝试过:

Function TFrmEmbeddedExe.StartNewApplication : Boolean; var SEInfo: TShellExecuteInfo; ExitCode : DWORD; begin FillChar(SEInfo, SizeOf(SEInfo), 0) ; SEInfo.cbSize := SizeOf(TShellExecuteInfo) ; with SEInfo do begin fMask := SEE_MASK_NOCLOSEPROCESS; Wnd := self.Handle; lpFile := PChar(self.fexecuteFileName) ;// Example could be 'C:\Windows\Notepad.exe' nShow := SW_SHOWNORMAL;//SW_HIDE; end; if ShellExecuteEx(@SEInfo) then begin sleep(1500); self.fAppWnd := FindWindow(nil, PChar(self.fWindowCaption)); //Example : 'Untitled - Notepad' if self.fAppWnd <> 0 then begin Windows.SetParent(self.fAppWnd, SEInfo.Wnd); ShowWindow(self.fAppWnd, SW_SHOWMAXIMIZED); result := true; end else result := false; end else result := false; end ; 

上面的代码实际上工作,但findWindow将find我开始的应用程序的任何给定instan。 我想embedded我Shellexecuted确切instu的。 所以如果记事本已经启动了几次,我不能使用FindWindow来获取正确的记事本。

我努力了:

 Function TfrmEmbeddedExe.CreateProcessNewApplication : Boolean; var zAppName: array[0..512] of char; StartupInfo: TStartupInfo; ProcessInfo: TProcessInformation; Res : DWORD; DoWait : Boolean; begin DoWait := False; StrPCopy(zAppName, self.fexecuteFileName); //'C:\Windows\Notepad.exe' FillChar(StartupInfo, Sizeof(StartupInfo), #0); StartupInfo.cb := Sizeof(StartupInfo); StartupInfo.dwFlags := STARTF_USESHOWWINDOW; StartupInfo.wShowWindow := SW_SHOWNORMAL; if CreateProcess (zAppName, nil, { 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) then { pointer to PROCESS_INF } begin if DoWait then //just set it to false... so it will never enter here begin WaitforSingleObject(ProcessInfo.hProcess, INFINITE); GetExitCodeProcess(ProcessInfo.hProcess, Res); end else begin self.fAppWnd := ProcessInfo.hProcess; Windows.SetParent(self.fAppWnd, self.Handle); ShowWindow(self.fAppWnd, SW_SHOWMAXIMIZED); CloseHandle(ProcessInfo.hProcess); CloseHandle(ProcessInfo.hThread); end; result := true; end else begin Result := false; end; end; 

请不要跑上面的代码! 它产生了奇怪的结果,包括在所有正在运行的应用程序的任何地方挑选一个看似随机的窗口,并embedded(甚至是Windows开始菜单中的菜单项)

所以基本上我需要的是如何启动一个应用程序,并获取应用程序主窗口的句柄。

任何帮助,高度赞赏

问候

延斯·福吉

以下是您需要做的粗略概述。 我将把编码留给你:

  1. 使用ShellExecuteExCreateProcess启动您的过程。 这将产生一个进程句柄。
  2. 在进程句柄上调用WaitForInputIdle 。 这为进程提供了加载和启动消息循环的机会。
  3. 将进程句柄传递给GetProcessId以获取进程ID。
  4. 使用EnumWindows来枚举顶层窗口。
  5. 将每个窗口传递给GetWindowThreadProcessId以检查是否找到了目标进程的顶级窗口。
  6. 一旦找到一个进程ID与你的目标进程匹配的窗口,你就完成了!

一旦你完成了它们,不要忘记关闭你的进程句柄。