全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:4071
推到 Plurk!
推到 Facebook!

如何抓到 ShellExecute 所開啟檔案 的 window handle

尚未結案
uj
一般會員


發表:14
回覆:25
積分:7
註冊:2003-03-06

發送簡訊給我
#1 引用回覆 回覆 發表時間:2003-04-03 17:50:40 IP:210.201.xxx.xxx 未訂閱
目前想到的是 等ShellExecute 開啟檔案 後 再來抓秀在最前面那個 但有點問題, 任意開啟一個檔案...不知多久會開得起來 請問有沒好一點的方法 HWND handle; HINSTANCE hInst = ShellExecute(handle, "open", "test.txt", NULL, NULL, SW_SHOWNORMAL); Sleep(1000); handleOpen = GetForegroundWindow();
RaynorPao
版主


發表:139
回覆:3622
積分:7025
註冊:2002-08-12

發送簡訊給我
#2 引用回覆 回覆 發表時間:2003-04-03 18:11:50 IP:61.221.xxx.xxx 未訂閱
引言: 目前想到的是 等ShellExecute 開啟檔案 後 再來抓秀在最前面那個 但有點問題, 任意開啟一個檔案...不知多久會開得起來 請問有沒好一點的方法 HWND handle; HINSTANCE hInst = ShellExecute(handle, "open", "test.txt", NULL, NULL, SW_SHOWNORMAL); Sleep(1000); handleOpen = GetForegroundWindow();
uj 你好: 是否先說明你的目的,也許有更簡單的方法喔 --
------
-- 若您已經得到滿意的答覆,請適時結案!! --
-- 欲知前世因,今生受者是;欲知來世果,今生做者是 --
-- 一切有為法,如夢幻泡影,如露亦如電,應作如是觀 --
uj
一般會員


發表:14
回覆:25
積分:7
註冊:2003-03-06

發送簡訊給我
#3 引用回覆 回覆 發表時間:2003-04-04 11:31:46 IP:61.56.xxx.xxx 未訂閱
多謝 RaynorPao 回覆 我用 ShellExecute 開啟檔案 後希望知道這 window 是否還開著 GetWindow( handleOpen, NULL ); 而某些情況我又想把他 關掉 if(handleOpen){ GetWindowThreadProcessId(handleOpen,&dwx); hProc = OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwx); TerminateProcess(hProc, 0); } 我想要做到這兩件事都需要知道 window handle 有看到討論 WaitForSingleObject(execinfo.hProcess,INFINITE); 好像也不合我的需求 另外我有收到另一封回覆的信函但是卻沒在討論區看到 請問是被刪掉了嗎
RaynorPao
版主


發表:139
回覆:3622
積分:7025
註冊:2002-08-12

發送簡訊給我
#4 引用回覆 回覆 發表時間:2003-04-04 11:58:41 IP:61.221.xxx.xxx 未訂閱
引言: 多謝 RaynorPao 回覆 我用 ShellExecute 開啟檔案 後希望知道這 window 是否還開著 GetWindow( handleOpen, NULL ); 而某些情況我又想把他 關掉 if(handleOpen){ GetWindowThreadProcessId(handleOpen,&dwx); hProc = OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwx); TerminateProcess(hProc, 0); } 我想要做到這兩件事都需要知道 window handle 有看到討論 WaitForSingleObject(execinfo.hProcess,INFINITE); 好像也不合我的需求 另外我有收到另一封回覆的信函但是卻沒在討論區看到 請問是被刪掉了嗎
uj 你好:
以下是我的建議,參考看看
(>    -- 
        
------
-- 若您已經得到滿意的答覆,請適時結案!! --
-- 欲知前世因,今生受者是;欲知來世果,今生做者是 --
-- 一切有為法,如夢幻泡影,如露亦如電,應作如是觀 --
uj
一般會員


發表:14
回覆:25
積分:7
註冊:2003-03-06

發送簡訊給我
#5 引用回覆 回覆 發表時間:2003-04-08 11:33:41 IP:210.201.xxx.xxx 未訂閱
多謝 RaynorPao 的回覆 還寫了一段 source code...感謝  只是我想這樣似乎不能確定找到的 > 誰知道較好的方法請告訴我
Justmade
版主


發表:94
回覆:1934
積分:2030
註冊:2003-03-12

發送簡訊給我
#6 引用回覆 回覆 發表時間:2003-04-08 13:39:56 IP:218.16.xxx.xxx 未訂閱
較可靠的方法 : 1. 用 FindExecutable 找出執行檔(連 Full Path) 2. 用 CreateProcess 來開啟檔案 3. 從 CreateProcess 回傳的 TProcessInformation 提取 dwProcessId 及 hProcess 4. 要取得 Window Handle 較煩,先用 hProcess 給 WaitForInputIdle 去等 Application 完成啟動 5. 使用 EnumWindows 並使用 dwProcessId 作 lParam 去對應出該 Process 的各個 windows 6. 從那些 Windows 找出 MainWindows (沒100%準確的方法,一般是看是否 Hidden, 有沒有 Caption, 是否沒 ParentWindow 等等) 7. 你亦可在 CreateProcess 前先在TStartupInfo設定一些特別的主視窗大小位置以便在 EnumWindows 後作對應條件,可大大的增加認出 Main Window 的機會。 這是我上年花了一個星期在網上找資料及實作的結果,亦成功地在 Delphi 做了出來,但找 WindowHandle 真的沒辦法 100% 準確。若有其他可從 ProcessID 或 hProcess 可準確找到 MainWindow Handle 的方法我亦很想知道。
RaynorPao
版主


發表:139
回覆:3622
積分:7025
註冊:2002-08-12

發送簡訊給我
#7 引用回覆 回覆 發表時間:2003-04-10 01:15:23 IP:61.221.xxx.xxx 未訂閱
引言: 多謝 RaynorPao 的回覆 還寫了一段 source code...感謝 只是我想這樣似乎不能確定找到的 > 誰知道較好的方法請告訴我 < face="Verdana, Arial, Helvetica"> uj 你好: 請參考以下的做法 < class="code"> HWND ghwnd; BOOL CALLBACK MyEnumWndProc5(HWND hWnd, LPARAM lParam); BOOL CALLBACK MyEnumWndProc5(HWND hWnd, LPARAM lParam) { DWORD id; GetWindowThreadProcessId(hWnd, &id); if(id==(DWORD)lParam) { ghwnd=hWnd; return FALSE; } return TRUE; } //.................................................................... ghwnd=NULL; STARTUPINFO si; PROCESS_INFORMATION pi; ZeroMemory(&si, sizeof(STARTUPINFO)); si.cb=sizeof(STARTUPINFO); CreateProcess(NULL, "notepad.exe test.txt", NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi); WaitForInputIdle(pi.hProcess, 4000); EnumWindows((WNDENUMPROC)MyEnumWndProc5, (LPARAM)pi.dwProcessId); if(ghwnd) { char szCaption[256]={0}; GetWindowText(ghwnd, szCaption, 256); ShowMessage(szCaption); } //.................................................................... -- Enjoy Researching & Developing --
------
-- 若您已經得到滿意的答覆,請適時結案!! --
-- 欲知前世因,今生受者是;欲知來世果,今生做者是 --
-- 一切有為法,如夢幻泡影,如露亦如電,應作如是觀 --
uj
一般會員


發表:14
回覆:25
積分:7
註冊:2003-03-06

發送簡訊給我
#8 引用回覆 回覆 發表時間:2003-04-21 15:30:14 IP:61.56.xxx.xxx 未訂閱
多謝 RaynorPao 與 Justmade 指教 我想做的是 開啟不固定的檔案類型 ( txt, zip, doc...等) 所以我用ShellExecute, 但似乎又無法明確的抓到所開啟的window handle RaynorPao 兄所提的 CreateProcess 的第二個參數 command line , 須自行去指定所開啟檔案的執行檔... 這樣一來...我就得自行依照其副檔名來找系統中可以開檔的ap... 有沒簡單些的用法
RaynorPao
版主


發表:139
回覆:3622
積分:7025
註冊:2002-08-12

發送簡訊給我
#9 引用回覆 回覆 發表時間:2003-04-21 15:42:39 IP:203.73.xxx.xxx 未訂閱
引言: 多謝 RaynorPao 與 Justmade 指教 我想做的是 開啟不固定的檔案類型 ( txt, zip, doc...等) 所以我用ShellExecute, 但似乎又無法明確的抓到所開啟的window handle RaynorPao 兄所提的 CreateProcess 的第二個參數 command line , 須自行去指定所開啟檔案的執行檔... 這樣一來...我就得自行依照其副檔名來找系統中可以開檔的ap... 有沒簡單些的用法
uj 你好: 其實~~這個問題我也已經想了很久,也做了很多實驗< > 但是~~似乎還找不到一個比較簡單的方法來達成目的< > 你說的問題,目前也只能夠使用 Win32 API FindExecutable 先找到檔案所對應的執行檔(exe),然後再用 CreateProcess 執行 如果覺得可以的話,就先暫時這樣使用吧,有空我再想一想 --
------
-- 若您已經得到滿意的答覆,請適時結案!! --
-- 欲知前世因,今生受者是;欲知來世果,今生做者是 --
-- 一切有為法,如夢幻泡影,如露亦如電,應作如是觀 --
brant
一般會員


發表:1
回覆:64
積分:23
註冊:2003-04-07

發送簡訊給我
#10 引用回覆 回覆 發表時間:2003-04-21 16:46:51 IP:61.219.xxx.xxx 未訂閱
引言: 多謝 RaynorPao 與 Justmade 指教 我想做的是 開啟不固定的檔案類型 ( txt, zip, doc...等) 所以我用ShellExecute, 但似乎又無法明確的抓到所開啟的window handle RaynorPao 兄所提的 CreateProcess 的第二個參數 command line , 須自行去指定所開啟檔案的執行檔... 這樣一來...我就得自行依照其副檔名來找系統中可以開檔的ap... 有沒簡單些的用法
用 ShellExecuteEx 如何? 把 fMask 設上 SEE_MASK_NOCLOSEPROCESS 就可從 hProcess 的 output 欄位來讀出開啟的 handle 但條件是一定要是新開啟的 process ,如果程式就已經開啟,只是多開一個 MDI 的子視窗來顯示的話,會傳回 NULL,這點要特別注意。
RaynorPao
版主


發表:139
回覆:3622
積分:7025
註冊:2002-08-12

發送簡訊給我
#11 引用回覆 回覆 發表時間:2003-04-21 22:49:37 IP:61.221.xxx.xxx 未訂閱
引言: 用 ShellExecuteEx 如何? 把 fMask 設上 SEE_MASK_NOCLOSEPROCESS 就可從 hProcess 的 output 欄位來讀出開啟的 handle 但條件是一定要是新開啟的 process ,如果程式就已經開啟,只是多開一個 MDI 的子視窗來顯示的話,會傳回 NULL,這點要特別注意。
brant 你好: 是否能夠冒昧的請教你?? 你有實際試過這個方法嗎??< > 老實說,我第一個實驗的方法,就是你說的這個方法< > 但是,一直沒有辦法成功(找不到用 ShellExecuteEx 執行的 Window Handle) 如果你有這方面的經驗的話,是否願意跟大家分享你的程式碼呢?? --
------
-- 若您已經得到滿意的答覆,請適時結案!! --
-- 欲知前世因,今生受者是;欲知來世果,今生做者是 --
-- 一切有為法,如夢幻泡影,如露亦如電,應作如是觀 --
brant
一般會員


發表:1
回覆:64
積分:23
註冊:2003-04-07

發送簡訊給我
#12 引用回覆 回覆 發表時間:2003-04-22 11:23:15 IP:61.219.xxx.xxx 未訂閱
用 ShellExecuteEx 得到的不是 window handle 而是 process handle 以下的 code 可以控制被開啟的外部程式:
 
        SHELLEXECUTEINFO ExecInfo;
        DWORD exit_code;
        int i=0;            memset(&ExecInfo,0,sizeof(SHELLEXECUTEINFO));
        ExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
        ExecInfo.fMask=SEE_MASK_NOCLOSEPROCESS;
        ExecInfo.hwnd = NULL;
        ExecInfo.lpFile = "c:\\test.txt";
        ExecInfo.nShow = SW_SHOWNORMAL;
        MessageBox(NULL,"三十秒後自動關閉","開啟外部檔案",MB_OK);
        ShellExecuteEx(&ExecInfo);
        
        GetExitCodeProcess(ExecInfo.hProcess,&exit_code);
        while (exit_code==STILL_ACTIVE) {
                i  ;
                Sleep(1000);
                if (i==30) {
                        TerminateProcess(ExecInfo.hProcess,0);
                        break;
                }
                GetExitCodeProcess(ExecInfo.hProcess,&exit_code);
        }
        if (i!=30) {
                MessageBox(NULL,"程式已被使用者關閉","開啟外部檔案",MB_OK);
        }
發表人 - brant 於 2003/04/22 11:43:28
Justmade
版主


發表:94
回覆:1934
積分:2030
註冊:2003-03-12

發送簡訊給我
#13 引用回覆 回覆 發表時間:2003-04-23 21:32:54 IP:218.16.xxx.xxx 未訂閱
引言: uj 你好: 請參考以下的做法 < class="code"> HWND ghwnd; BOOL CALLBACK MyEnumWndProc5(HWND hWnd, LPARAM lParam); BOOL CALLBACK MyEnumWndProc5(HWND hWnd, LPARAM lParam) { DWORD id; GetWindowThreadProcessId(hWnd, &id); if(id==(DWORD)lParam) { ghwnd=hWnd; return FALSE; } return TRUE; } //.................................................................... ghwnd=NULL; STARTUPINFO si; PROCESS_INFORMATION pi; ZeroMemory(&si, sizeof(STARTUPINFO)); si.cb=sizeof(STARTUPINFO); CreateProcess(NULL, "notepad.exe test.txt", NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi); WaitForInputIdle(pi.hProcess, 4000); EnumWindows((WNDENUMPROC)MyEnumWndProc5, (LPARAM)pi.dwProcessId); if(ghwnd) { char szCaption[256]={0}; GetWindowText(ghwnd, szCaption, 256); ShowMessage(szCaption); } //....................................................................
我不懂寫bcb所以只能談原理,看這程式碼應是和我說的原理相若罷,大家果然所見略同啊。 不過我上次實作時只找出第一個附合pi.dwProcessId的視窗真的不成耶,對notepad 是沒問題,對較複雜的程式找錯的機會很大,很多時會找了該程式的其他視窗(包括隱藏視窗)出來,加了第六點的測試便準確了很多但還不是100%,所以我覺得這還是需要的。 另外若 uj 接受抓秀在最前面那個視窗,其實亦可在 WaitForInputIdle 後去抓而不用 enumWindows,但其實也不大可靠因若使用者中途按了去別的程式便會抓錯了。
uj
一般會員


發表:14
回覆:25
積分:7
註冊:2003-03-06

發送簡訊給我
#14 引用回覆 回覆 發表時間:2003-05-08 15:47:21 IP:210.201.xxx.xxx 未訂閱
感謝 RaynorPao , Justmade , brant 的幫忙 我試到後來 brant 所說的方式似乎較能符合我的需求, 也較簡單 多謝各位啦
系統時間:2024-04-20 3:52:59
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!