C# Process.MainWindowHandle 总是返回 IntPtr 零

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16185217/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 00:17:28  来源:igfitidea点击:

C# Process.MainWindowHandle always returns IntPtr Zero

c#processintptrwindow-handles

提问by Kfir Eichenblat

this is my code:

这是我的代码:

            using (Process game = Process.Start(new ProcessStartInfo() { 
        FileName="DatabaseCheck.exe",
        RedirectStandardOutput = true,
        CreateNoWindow = true,
        UseShellExecute = false }))
        {
            lblLoad.Text = "Loading";
            int Switch = 0;

            while (game.MainWindowHandle == IntPtr.Zero)
            {
                Switch++;
                if (Switch % 1000 == 0)
                {
                    lblLoad.Text += ".";
                    if (lblLoad.Text.Contains("...."))
                        lblLoad.Text = "Loading.";

                    lblLoad.Update();
                    game.Refresh();
                }
            }

Problem is, that game.MainWindowHandle is always IntPtr.Zero. I need to find the IntPtr of the ran process to confirm that the game was started by the launcher, so I made the game send it's IntPtr and let the launcher respond if it's okay. But for that, I must know the IntPtr of the ran process specifically.

问题是,那个 game.MainWindowHandle 总是 IntPtr.Zero。我需要找到运行进程的 IntPtr 以确认游戏是由启动器启动的,所以我让游戏发送它的 IntPtr 并让启动器响应(如果可以的话)。但为此,我必须特别知道 run 进程的 IntPtr。

Thanks in advance!

提前致谢!

采纳答案by VS1

The main window is the window opened by the process that currently has the focus (the TopLevel form). You must use the Refreshmethod to refresh the Process object to get the current main window handle if it has changed.

主窗口是当前具有焦点的进程打开的窗口(TopLevel 窗体)。您必须使用该Refresh方法刷新 Process 对象以获取当前主窗口句柄(如果它已更改)

You can get the MainWindowHandleproperty only for processes that are running on the local computer. The MainWindowHandle property is a value that uniquely identifies the window that is associated with the process.

MainWindowHandle只能为在本地计算机上运行的进程获取该属性。MainWindowHandle 属性是唯一标识与进程关联的窗口的值。

A process has a main window associated with it only if the process has a graphical interface. If the associated process does not have a main window, the MainWindowHandle value is zero. The value is also zero for processes that have been hidden, that is, processes that are not visible in the taskbar. This can be the case for processes that appear as icons in the notification area, at the far right of the taskbar.

仅当进程具有图形界面时,进程才具有与其关联的主窗口。如果关联进程没有主窗口,则 MainWindowHandle 值为零。对于已隐藏的进程,即在任务栏中不可见的进程,该值也为零。对于在任务栏最右侧的通知区域中显示为图标的进程,可能就是这种情况。

If you have just started a process and want to use its main window handle, consider using the WaitForInputIdle method to allow the process to finish starting, ensuring that the main window handle has been created. Otherwise, an exception will be thrown.

如果您刚刚启动了一个进程并希望使用其主窗口句柄,请考虑使用 WaitForInputIdle 方法来允许进程完成启动,确保已创建主窗口句柄。否则,将抛出异常。

回答by ounami

while (!proc.HasExited)
{
    proc.Refresh();
    if (proc.MainWindowHandle.ToInt32() != 0)
    {
        return proc.MainWindowHandle;
    }
}

回答by dynamichael

A workaround is to enumerate through all top-level windows and examine their process ids until you find a match...

一种解决方法是枚举所有顶级窗口并检查它们的进程 ID,直到找到匹配项...


    [DllImport("user32.dll")]
    public static extern IntPtr FindWindowEx(IntPtr parentWindow, IntPtr previousChildWindow, string windowClass, string windowTitle);

    [DllImport("user32.dll")]
    private static extern IntPtr GetWindowThreadProcessId(IntPtr window, out int process);

    private IntPtr[] GetProcessWindows(int process) {
        IntPtr[] apRet = (new IntPtr[256]);
        int iCount = 0;
        IntPtr pLast = IntPtr.Zero;
        do {
            pLast = FindWindowEx(IntPtr.Zero, pLast, null, null);
            int iProcess_;
            GetWindowThreadProcessId(pLast, out iProcess_);
            if(iProcess_ == process) apRet[iCount++] = pLast;
        } while(pLast != IntPtr.Zero);
        System.Array.Resize(ref apRet, iCount);
        return apRet;
    }