Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/257.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么可以';无法获取已启动进程的主窗口句柄?_C#_Wpf_Mfc_Process_Ipc - Fatal编程技术网

C# 为什么可以';无法获取已启动进程的主窗口句柄?

C# 为什么可以';无法获取已启动进程的主窗口句柄?,c#,wpf,mfc,process,ipc,C#,Wpf,Mfc,Process,Ipc,我在代码中启动一个进程以设置IPC通道。我启动的进程是一个不支持CLR的MFC应用程序。我启动此过程的应用程序是WPF应用程序中的一个C#模块(我认为这不是我的问题的结果)。这适用于不支持CLR的应用程序版本,并且它适用于除部署目标(带有Windows 7的触摸屏计算机)之外的所有计算机。但由于某些原因,当我尝试使用这个确切的场景时,Process对象从未解析主窗口句柄(Process.MainWindowHandle)。有没有其他的方法(也许甚至是pinvoke)来做到这一点?这是安全问题吗?

我在代码中启动一个进程以设置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

我的习惯是在与GetWindowThreadProcessId结合的循环中调用EnumWindows以查找窗口句柄

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;
}

我不知道为什么会有所不同,但创建流程后,请尝试执行以下操作:

Process[] allProcesses = Process.GetProcessesByName("YourWindowTitle");

并查看返回的进程是否有MainWindowHandle。

从Process.MainWindowHandle中得到的值很不幸是一个猜测。程序没有API函数可以告诉Windows“这是我的主窗口”。它使用的规则是有文档记录的,它是流程启动时创建的第一个窗口。如果第一个窗口是(比如)登录窗口或启动屏幕,则会导致问题


对此您无能为力,您必须更多地了解程序的行为,才能找到真正的主窗口。使用EnumThreadWindows()枚举窗口可以帮助您找到它,只要第一个窗口是在与主窗口相同的线程上创建的。如果不是这样,则需要更详细的EnumWindows()。

为了通过您的进程获得
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());
    }

您是否厌倦了按照MSDN文档的建议使用
waitForInputdle
?另外,最好使用
throw
而不是
throw ex
,因为
throw ex
会丢失堆栈跟踪信息(
throw ex
重新启动异常抛出,因此堆栈跟踪)。@jordan我看到了您的编辑。您需要在注释中包含@username,以便通知您回复的其他用户。@jordan在do\while循环中,我认为您将滴答与毫秒混淆了。滴答声是100纳秒。使用
秒表
可能更简单。@jordan可能值得考虑在循环中加入
线程。睡眠
来限制
刷新
调用。@chibacity不,这些都不起作用。我不认为@是必要的,因为你是唯一的评论者。这是不同的,但恰恰相反。以这种方式掌握一个过程,你没有充分的信任,因此不能用它做很多事情,当然也不能得到它的控制。只有当你开始一个过程时,你才能在任何有意义的意义上与之互动。这对我有什么帮助?我正在尝试从另一个进程获取窗口句柄。你能给我提供一些代码吗?所以基本上这会得到给定进程ID的所有窗口,很有趣。