C#Process.MainWindowHandle始终返回IntPtr Zero

Kfi*_*ods 12 c# process window-handles intptr

这是我的代码:

            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();
                }
            }
Run Code Online (Sandbox Code Playgroud)

问题是,那个游戏.MainWindowHandle总是IntPtr.Zero.我需要找到运行过程的IntPtr以确认游戏是由启动器启动的,所以我让游戏发送它的IntPtr并让启动器响应它是否正常.但为此,我必须具体了解运行过程的IntPtr.

提前致谢!

VS1*_*VS1 13

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

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

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

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


小智 6

while (!proc.HasExited)
{
    proc.Refresh();
    if (proc.MainWindowHandle.ToInt32() != 0)
    {
        return proc.MainWindowHandle;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 您好,您的帖子已被标记为“低质量”,可能是因为它仅由代码组成。您可以通过提供对如何以及为什么回答问题的确切解释来大大改善您的答案? (3认同)
  • 对于阅读这篇旧帖子的任何人......我记得在某个地方读到过,由于 x64 与 x86,使用类似的东西并不是一个好主意。最好使用 `IntPtr.Zero != proc.MainWindowHandle` 代替。 (2认同)

dyn*_*ael 5

解决方法是枚举所有顶级窗口并检查其进程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;
    }
Run Code Online (Sandbox Code Playgroud)