接上一篇。
再說一遍需求:寫一個程式A,去啟動一個指定的程式B,設定它的視窗大小并把它放到指定位置。
既然CreateProcess指定的程式啟動參數,對于GUI程式無效(我暫時真的不知道為什麼…),那可以讓程式啟動以後,擷取它的Handle,然後模拟作業系統向它發送消息,讓其響應。
CreateProcess可以得到被啟動的程式的PID,但得不到handle。(我也不知道怎麼回事,明明說傳回的是個handle,但确實和B的handle不是一個數,另外嘗試了各種辦法,比如openProcess傳回的也不是B的handle的數)
那麼,如果根據PID找到它對應的handle呢?
方法一,調用GetWindowThreadProcessId函數。
有可能有死循環…,就是可能一直都找不到。
一個坑!
如果開啟的不是gui程式,隻是開個控制台,也找不到!啟動以後,CreateProcess立即傳回了。wait那個函數沒有生效!就算是Sleep以後,也找不到……
vc++6.0編譯,xp系統和win8系統,測試通過。
注意,因為前面是getForeground,是以後面是寫GetNextWindow的參數傳的是Prev…
有幾個函數,getWindow,getTopWindow,getForeground...
GetNext...的參數有prev、next。

GetWindowThreadProcessId
The GetWindowThreadProcessId function retrieves the identifier of the thread that created the specified window and, optionally, the identifier of the process that created the window.
DWORD GetWindowThreadProcessId( HWNDhWnd,// handle to window
LPDWORDlpdwProcessId // address of variable for process identifier
);
Parameters
hWnd
Handle to the window.
lpdwProcessId
Pointer to a 32-bit value that receives the process identifier. If this parameter is not NULL,
GetWindowThreadProcessId copies the identifier of the process to the 32-bit value; otherwise, it does not.
Return Values
The return value is the identifier of the thread that created the window.
WaitForInputIdle
The WaitForInputIdle function waits until the given process is waiting for user input with no input pending, or until the time-out interval has elapsed.
The WaitForInputIdle function only works with GUI applications. If a console application calls the function, it returns immediately, with no wait.
DWORD WaitForInputIdle( HANDLEhProcess,// handle to process
DWORDdwMilliseconds // time-out interval in milliseconds
);
Parameters
hProcess
Handle to the process.
dwMilliseconds
Specifies the time-out interval, in milliseconds. If
dwMilliseconds is INFINITE, the function does not return until the process is idle.
Return Values
The following table shows the possible return values:
Value
Meaning
The wait was satisfied successfully.
WAIT_TIMEOUT
The wait was terminated because the time-out interval elapsed.
0xFFFFFFFF
An error occurred. To get extended error information, use the GetLastError function.
Remarks
The WaitForInputIdle function enables a thread to suspend its execution until a specified process has finished its initialization and is waiting for user input with no input pending. This can be useful for synchronizing a parent process and a newly created child process. When a parent process creates a child process, the CreateProcess function returns without waiting for the child process to finish its initialization. Before trying to communicate with the child process, the parent process can use WaitForInputIdle to determine when the child's initialization has been completed. For example, the parent process should use WaitForInputIdle before trying to find a window associated with the child process.
The WaitForInputIdle function can be used at any time, not just during application startup.
方法二,調用EnumWindows函數。枚舉視窗。
有個問題需要注意。
如果啟動的不是GUI,waitForInputldle沒有用。需要手動指定一個Sleep的時間。或者就用B向A發消息通知一下。或者B啟動完畢後在哪個地方标記一下,記憶體也好硬碟也好,然後A去輪詢這個位置。
廢話不多說了,上代碼。
#include
#include
BOOL CALLBACK EnumWindowsProc(HWND hwnd, // handle to parent window
LPARAM lParam // application-defined value
){
if (IsWindowVisible(hwnd)) {
char title[1000];
GetWindowText(hwnd,title,1000);
printf("%s\n",title);
unsigned long find_pid = 0;
GetWindowThreadProcessId(hwnd, &find_pid);
if(find_pid == lParam){
printf("已找到\n");
printf("%s, 0x%x, %d\t",title, hwnd,lParam);
}
// printf("%d, %d\n", find_pid, lParam);
}
return TRUE;
}
int main (int argc,char* argv[])
{
char szCommandLine[]="calc.exe";
STARTUPINFO si={sizeof(si)};
PROCESS_INFORMATION pi;
si.dwY = 0;
si.dwX = 0;
si.dwXSize = 200;
si.dwYSize = 100;
si.dwFlags=STARTF_USESHOWWINDOW | STARTF_USEPOSITION | STARTF_USESIZE; //制定wShowWindow成員
si.wShowWindow=TRUE; //為真,顯示程序的主視窗
BOOL bRet=::CreateProcess(
NULL,//不在此指定可執行檔案的檔案名
szCommandLine, //指令行參數
NULL,//預設程序的安全性
NULL,//預設線程的安全性
FALSE,//指定目前程序内的句柄不可以被子程序繼承
CREATE_NEW_CONSOLE,//為新程序建立一個新的控制台視窗
NULL,//使用本程序的環境變量
NULL,//使用本程序的驅動器和目錄
&si,
&pi);
if(bRet)
{
WaitForInputIdle(pi.hProcess,INFINITE);
Sleep(1000);
EnumWindows(EnumWindowsProc,pi.dwProcessId);
::CloseHandle(pi.hThread);
::CloseHandle(pi.hProcess);
printf("新的程序的程序ID号:%d\n",pi.dwProcessId);
printf("新程序的主線程ID号:%d\n",pi.dwThreadId);
}
return 0;
}
