以下是该方案:
我有2个应用。其中一个是我的主要应用程序,第二个是基于对话框的应用程序,从第一个应用程序启动。我正试图从我的主应用程序捕获基于对话框的应用程序的主要句柄。问题是我无法用EnumWindows找到它。如果我在开始枚举窗口之前暂停一下,问题就会消失。
这是代码:
...
BOOL res = ::CreateProcess( NULL, _T("MyApp.exe"), NULL, NULL, FALSE, NULL, NULL, NULL, &siStartInfo, &piProcInfo );
ASSERT(res);
dwErr = WaitForInputIdle(piProcInfo.hProcess, iTimeout);
ASSERT(dwErr == 0);
//Sleep(1000); //<-- uncomment this will fix the problem
DWORD dwProcessId = piProcInfo.dwProcessId;
EnumWindows(EnumWindowsProc, (LPARAM)&dwProcessId);
....
BOOL IsMainWindow(HWND handle)
{
return GetWindow(handle, GW_OWNER) == (HWND)0 && IsWindowVisible(handle);
}
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
DWORD* pParam = (DWORD*)lParam;
DWORD dwTargetProcessId = *pParam;
DWORD dwProcessId = 0;
::GetWindowThreadProcessId(hwnd, &dwProcessId);
if (dwProcessId == dwTargetProcessId )
{
TCHAR buffer[MAXTEXT];
::SendMessage(hwnd, WM_GETTEXT, (WPARAM)MAXTEXT,(LPARAM)buffer);
if( IsMainWindow(hwnd))
{
g_hDlg = hwnd;
return FALSE;
}
}
return TRUE;
}
正好有2个窗口属于我的进程,并且跟踪文本显示:
GDI+ Window
Default IME
我不太清楚这是什么意思。这些可能是在初始化之前分配给窗口的默认标题....但我在WaitForInputIdle之后调用EnumWindows ...
任何帮助将不胜感激。
答案 0 :(得分:3)
CreateProcess
返回。这并不意味着该流程已经开始执行。
如果您需要查询另一个进程以获取仅在该进程运行到某个点后才可用的信息,则需要安装某种同步。一个明显的选项是命名事件对象(请参阅CreateEvent),当第二个进程完成初始化并且对话框启动并运行时,该对象将发出信号。然后,第一个过程将只是WaitForSingleProcess,并且只有在发出事件信号后才会继续。 (更强大的解决方案是在事件和进程句柄上调用WaitForMultipleObjects,以响应意外的进程终止。)
另一种选择是让第二个进程向第一个进程发送用户定义的消息(WM_APP+x
),并传递其HWND
。
WaitForInputIdle听起来像是一个可行的解决方案。除此之外,它不是。引入WaitForInputIdle
是为了满足DDE的要求,并且只检查目标进程中的线程是否可以接收消息。这真的意味着该进程中的任何线程。它并不严格依赖于正在运行的GUI。
有关该主题的更多信息,请访问: