How to run the application and get it using Delphi?

I want to run an application from Delphi and get a handle for it, so I can embed the main window of the application in a frame of type TFrame. So far I have tried:

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 ;

The above code does work, but findWindow will find any data to run the application. I want to embed the exact instances that I made Shellexecuted. Therefore, if Notepad was launched a couple of times, I cannot get the correct option using FindWindow.

I tried:

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;

PLEASE DO NOT MISS THE ABOVE CODE! It creates strange results associated with choosing a random window anywhere in all running applications and an attachment (even menu items from the Windows Start menu).

, , .

+5
1

, . :

  • ShellExecuteEx CreateProcess. .
  • WaitForInputIdle . .
  • GetProcessId, .
  • EnumWindows .
  • GetWindowThreadProcessId, , .
  • , , !

, .

+9

All Articles