ShellExecute 與 FindWindow組合使用還有什摩要注意? |
尚未結案
|
chris_shieh
高階會員 發表:46 回覆:308 積分:240 註冊:2004-04-26 發送簡訊給我 |
我利用ShellExecute 執行一些外部程式 (xx.bat)
並在ShellExecute 指令後 立即使用 FindWindow 取得其 HWND
以便SetWindowPos 可以使用
發現一個奇怪現象
當外部程式數目很少時 可以順利動作
但是當外部程式數目較多時
部分(通常是較後面執行者)無法順利抓到HWND (為0)
但是又不是每次都會這樣, 這現象令我狐疑
結果我利用加入sleep()在ShellExecute之後, FindWindow 之前
試驗結果發現
當程式數目較少, 短的sleep時間時間即可正常運作,
當成是數目增多, 相對也需要增加sleep時間才能正常運作
(大約是8-10個 *.bat sleep(1500))
不知道我是哪邊應注意而未注意呢? var
psei:^TShellExecuteInfo;
hwnd:THandle;
windowCaption:String; for i=0 to scriptList.Count-1 do
begin
New(psei);
with psei^ do
begin
FillChar(psei^, SizeOf(psei^), 0);
cbSize:=Sizeof(psei^);
fMask:=SEE_MASK_NOCLOSEPROCESS ; // 用來取得 ProcessID
wnd:=0;
lpVerb:=nil;
lpFile:=PChar(scriptList[i]);
lpParameters:=nil;
lpDirectory:=nil;
nShow:=SW_SHOWDEFAULT;
end ;
ShellExecuteEx(@psei^);
sleep(1500); //少了這行, 通常會遺漏幾個視窗抓不到hwnd
hwnd:=FindWindow(nil, PChar(windowCaption));
SetWindowPos(hwnd,0,10,10,200,200,SWP_SHOWWINDOW)
end;
|
hagar
版主 發表:143 回覆:4056 積分:4445 註冊:2002-04-14 發送簡訊給我 |
改用如下這個方法試試
用法為傳入 exe 檔(含完整路徑),
其回傳值為執行該 exe 後的 window handle
資料來源: http://delphi.ktop.com.tw/topic.php?topic_id=35055
function PlayFlashExe(Exe: string): integer; type PEnumInfo = ^TEnumInfo; TEnumInfo = record ProcessID: DWORD; HWND: THandle; end; function EnumWindowsProc(Wnd: DWORD; var EI: TEnumInfo): Bool; stdcall; var PID: DWORD; begin GetWindowThreadProcessID(Wnd, @PID); Result := (PID <> EI.ProcessID) or (not IsWindowVisible(WND)) or (not IsWindowEnabled(WND)); if not result then EI.HWND := WND; end; function FindMainWindow(PID: DWORD): DWORD; var EI: TEnumInfo; begin EI.ProcessID := PID; EI.HWND := 0; EnumWindows(@EnumWindowsProc, Integer(@EI)); Result := EI.HWND; end; var SI: TStartupInfo; PI: TProcessInformation; begin ZeroMemory(@SI, SizeOf(SI)); ZeroMemory(@PI, SizeOf(PI)); SI.cb := SizeOf(SI); if CreateProcess(nil, PChar(FlashExe), nil, nil, FALSE, 0 ,nil,nil, SI, PI) then begin WaitForInputIdle(PI.hProcess, INFINITE); Result := FindMainWindow(PI.dwProcessID); CloseHandle(PI.hProcess); CloseHandle(PI.hThread); end; end;-- 悟嗎? |
chris_shieh
高階會員 發表:46 回覆:308 積分:240 註冊:2004-04-26 發送簡訊給我 |
[quote]
改用如下這個方法試試
用法為傳入 exe 檔(含完整路徑),
其回傳值為執行該 exe 後的 window handle
資料來源: http://delphi.ktop.com.tw/topic.php?topic_id=35055
function PlayFlashExe(Exe: string): integer; type PEnumInfo = ^TEnumInfo; TEnumInfo = record ProcessID: DWORD; HWND: THandle; end; function EnumWindowsProc(Wnd: DWORD; var EI: TEnumInfo): Bool; stdcall; var PID: DWORD; begin GetWindowThreadProcessID(Wnd, @PID); Result := (PID <> EI.ProcessID) or (not IsWindowVisible(WND)) or (not IsWindowEnabled(WND)); if not result then EI.HWND := WND; end; function FindMainWindow(PID: DWORD): DWORD; var EI: TEnumInfo; begin EI.ProcessID := PID; EI.HWND := 0; EnumWindows(@EnumWindowsProc, Integer(@EI)); Result := EI.HWND; end; var SI: TStartupInfo; PI: TProcessInformation; begin ZeroMemory(@SI, SizeOf(SI)); ZeroMemory(@PI, SizeOf(PI)); SI.cb := SizeOf(SI); if CreateProcess(nil, PChar(FlashExe), nil, nil, FALSE, 0 ,nil,nil, SI, PI) then begin WaitForInputIdle(PI.hProcess, INFINITE); Result := FindMainWindow(PI.dwProcessID); CloseHandle(PI.hProcess); CloseHandle(PI.hThread); end; end;============================================================== 感謝hagar, 當然以 EnumWindow方式列舉更能精確從Process Handle找出其 handle, 但是很遺憾的, 我採用您的方式, 一樣必須在 CreateProcess與FindMainWindow之間加上sleep()才能正常抓到所有視窗, 過短的sleep 依然會遺漏部份視窗, 跟之前的程式碼結果一樣, 真是奇怪, 難道這跟所執行的程式有關嗎? (可是畢竟已經加上WaitForInputIdle了), ps.我所執行的*.bat 會去存取HDD一些不存在的目錄並且有loop動作 |
chris_shieh
高階會員 發表:46 回覆:308 積分:240 註冊:2004-04-26 發送簡訊給我 |
參考 http://delphi.ktop.com.tw/topic.php?TOPIC_ID=49601
跟小弟同樣情形, 改成多找幾次, 就都OK, 不過對於原因還是很納悶
而且也會拉長時間 >
|
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |