2012-09-05 11 views
5

Delphi'den bir uygulama başlatmak ve bir tanıtıcı elde etmek istiyorum, bu nedenle söz konusu uygulamanın ana penceresini TFrame tipi bir çerçeveye gömebilirim.Uygulama nasıl başlatılır ve Delphi ile nasıl bir tanıtıcı elde edilir?

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 ; 

Yukarıdaki kod aslında çalışır, ancak FindWindow başladığım uygulamanın herhangi bir instans bulacaksınız: Şimdiye kadar ben denedim. Ben Shellexecuted Ben tam instans gömmek istiyorum. Notepad bir kaç kez başlatılmış olsaydı, FindWindow'u kullanarak doğru olanı elde etmenin bir yolu yoktur.

denedim:

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; 

Yukarıdaki kod çalıştırabilir YAPMAYIN LÜTFEN! Bu, tüm çalışan uygulamalarda herhangi bir yerde rastgele bir pencere seçmenin ve onu gömmenin (Windows başlat menüsünden menü öğelerini bile içerir) garip sonuçlar doğurur.

Temel olarak ihtiyacım olan şey bir uygulamayı nasıl başlatırım uygulamalar ana penceresine bir tutamaç.

Herhangi bir yardım son derece

Saygılar

Jens Fudge

+5

Bir işlem tanıtıcısı, bir pencere tanıtıcısı değildir. Bkz. Http://stackoverflow.com/questions/1888863/how-to-get-main-window-handle-from-process-id –

+0

Başlığı okumak için, gelmek üzereydim ve bu * olması gerektiğini ısrar etmek * Yinelenen, ancak bu uygulamayı kendi içine gömdüğünüzü gördükten sonra, bunu ayrı ayrı yapar. Harika soru. –

+0

Lütfen yayınınıza imza eklemeyin. [StackOverflow zaten sizin için bir tane gösterir] (http://stackoverflow.com/faq#signatures). – Deanna

cevap

9

İşte yapmanız gerekenler kaba anahat takdir edilmektedir. Sana kodlama kadar bırakacağım:

  1. ShellExecuteEx veya CreateProcess ya ile işlemini başlatın. Bu işlem tanıtıcısı verecektir.
  2. İşlem tanıtıcısı üzerinde WaitForInputIdle numaralı telefonu arayın. Bu işlemin mesaj döngüsünü yükleme ve başlatma şansını verir.
  3. İşlem kimliğini elde etmek için işlem kolunu GetProcessId'a aktarın.
  4. Üst düzey pencereleri numaralandırmak için EnumWindows'u kullanın.
  5. Hedef işleminizin en üst düzey penceresini bulup bulamayacağınızı kontrol etmek için bu pencerelerin her birini GetWindowThreadProcessId'a geçirin.
  6. İşlem kimliğinizin hedef sürecinizle eşleştiği bir pencere bulduğunuzda, işiniz bitti!

İşlem bittikten sonra işlem tutamaçlarını kapatmayı unutmayın.

+0

David Heffernan, bu gerçekten ileriye gitmek için bir yol gibi geliyor, ve ben sadece zaman aldığımda yapacağım. Açıklamak için çok teşekkürler. –

İlgili konular