我有一种情况,我在我的代码中启动一个进程,以便建立一个IPC通道。我正在开始的过程是一个没有CLR支持的MFC应用程序。我开始这个过程的应用程序是WPF应用程序中的C#模块(我认为这不是我的问题的结果)。这适用于支持CLR的应用程序版本,它适用于除部署目标之外的每台计算机,Windows 7的触摸屏计算机。但出于某种原因,当我尝试使用此确切方案时,Process对象永远不会解析主窗口句柄(Process.MainWindowHandle
)。这样做有另一种(甚至是pinvoke)方法吗?这是安全的事吗?我是那个盯着这个过程的人。进程的主窗口句柄确实存在。我看不出有什么不对。
如果有帮助,这是我的代码。
_applicationProcess = new Process();
_applicationProcess.StartInfo.FileName = _strProcessPath;
_applicationProcess.StartInfo.Arguments = _strProcessArguments;
_applicationProcess.Start();
long nTicks = Environment.TickCount;
if (_applicationProcess.WaitForInputIdle(1 /*minute(s)*/ * 60000))
{
try
{
do
{
// Don't let total processing take more than 1 minute(s).
if (Environment.TickCount > nTicks + 1 /*minute(s)*/ * 60000)
throw new ApplicationException("MFCApplication.Startup failed! The main window handle is zero!");
_applicationProcess.Refresh();
}
while (_applicationProcess.MainWindowHandle.ToInt32() == 0);
_applicationHandle = new IntPtr(_applicationProcess.MainWindowHandle.ToInt32());
}
catch (Exception ex)
{
//Do some stuff...
throw;
}
}
else
{
// Do exception handling.
}
在尝试获取非零的主窗口句柄一分钟后,ApplicationException
被点击。
答案 0 :(得分:6)
不幸的是,您从Process.MainWindowHandle获得的值是猜测。程序没有可用的API函数让它告诉Windows“这是我的主窗口”。它使用的规则是记录的,它是进程启动时创建的第一个窗口。如果第一个窗口是登录窗口或启动画面,则会导致问题。
你无能为力,你必须更多地了解程序如何找到真正的主窗口。只要第一个窗口是在与主窗口相同的线程上创建的,使用EnumThreadWindows()枚举窗口就可以帮助您找到它。如果不是这样的话,将需要更精细的EnumWindows()。
答案 1 :(得分:3)
我的习惯是在一个循环中调用EnumWindows并结合GetWindowThreadProcessId来查找窗口句柄。
C Code, adapt to your language
DWORD TargetHWND;
//...
while (EnumWindows(EnumWndProc, (LPARAM)(DWORD)pid)) {
Sleep(100);
}
//...
BOOL EnumWndProc(HWND hWnd, LPARAM lParam) {
DWORD pid = (DWORD)-1;
GetWindowThreadProcessId(hWnd, &pid);
if (pid == (DWORD)lParam) {
TargetHWND = hWnd;
return FALSE;
}
return TRUE;
}
答案 2 :(得分:2)
为了通过您的流程获得MainWindowHandle
,请确保您的WPF应用程序显示在任务栏上,即ShowInTaskbar="True"
,并将Application.Current.MainWindow
属性设置为您所在的窗口喜欢设置为主窗口。
如果我在WPF主窗口中执行下面的代码而没有设置ShowInTaskbar="True"
我总是得到0作为MainWindowHandle
,因为我的WPF窗口全屏并且没有显示在任务栏上。
Application.Current.MainWindow = this;
var Query = System.Diagnostics.Process.GetProcessesByName("ProcessName");
if (Query.Any())
{
Query.FirstOrDefault().Refresh();
MessageBox.Show(Query.FirstOrDefault().MainWindowHandle.ToInt32().ToString());
}
答案 3 :(得分:1)
我不知道为什么会有所不同,但在您创建流程后,请尝试:
Process[] allProcesses = Process.GetProcessesByName("YourWindowTitle");
并查看返回的任何进程是否具有MainWindowHandle。