如何在.NET中获取当前的窗口句柄计数和窗口句柄限制?

时间:2020-03-06 14:49:14  来源:igfitidea点击:

我想获取C#中当前的窗口句柄数和系统范围内的窗口句柄限制。我该怎么办?

解决方案

正如雷蒙德·陈(Raymond Chen)前段时间所说,如果我们正在考虑窗口句柄限制,那么我们可能做错了:)

无论如何,我敢打赌,没有特殊的Cway可以这样做,因为它是非常特定于系统的。我们可以使用与C ++应用程序中相同的功能。使用P / Invoke调用功能。要了解如何编写导入内容,请访问pinvoke.net。

编辑:据我所知,我假设我们已经知道如何在Win32应用程序中执行此操作。

OregonGhost引用的完整报价是

If you have to ask, you're probably doing something wrong.

这是为什么每个进程的窗口句柄限制为10,000个?你应该读这个。

如果我们阅读了Raymond Chen的文章,我们可能会发现它像我一样令人讨厌。我们只是在"可能做错了什么",因为我们在做Windows无法完成的事情。

在我的应用程序中,用户第一次访问选项卡页面时,我会在该页面上创建并布置所有控件。这需要花费大量的时间,一个页面上可以轻松地包含50个控件。因此,即使有可能,我也不会在标签页上丢弃控件(如果可能的话),并将关闭的标签页集留给用户使用。

碰巧的是,某些用户从不希望关闭任何选项卡页集。我为什么要强迫他们这样做?借助我的用户界面,他们可以非常快速地导航至他们负责管理的300多种交易中的任何一套。他们的机器足够快,并且有足够的内存,可以使所有这些都非常灵敏。唯一的问题是Windows无法支持它。

为什么我使用控件,而不使用其他UI技术?因为他们工作。我需要支持焦点事件,选项卡顺序,验证事件,动态布局和数据绑定,而用户实际上是在内存DataSet中管理数十个表中的数千条记录。我要说的要用无窗控件实现某些东西的开发量真是天文数字。

我只是"做错了",因为Windows对它可以支持的窗口句柄数量有严格的限制。这个硬性限制是基于关于计算机UI可能如何构建的数十年的假设。不是"做错了事"的人。

无论如何,我的解决方案分为两部分。

首先,一个可以告诉我们进程有多少窗口句柄的类正在使用:

using System;
using System.Runtime.InteropServices;

namespace StreamWrite.Proceedings.Client
{
    public class HWndCounter
    {
        [DllImport("kernel32.dll")]
        private static extern IntPtr GetCurrentProcess();

        [DllImport("user32.dll")]
        private static extern uint GetGuiResources(IntPtr hProcess, uint uiFlags);

        private enum ResourceType
        {
            Gdi = 0,
            User = 1
        }

        public static int GetWindowHandlesForCurrentProcess(IntPtr hWnd)
        {
            IntPtr processHandle = GetCurrentProcess();
            uint gdiObjects = GetGuiResources(processHandle, (uint)ResourceType.Gdi);
            uint userObjects = GetGuiResources(processHandle, (uint)ResourceType.User);

            return Convert.ToInt32(gdiObjects + userObjects);
        }
    }
}

其次,我为我的标签页对象保留了最近最少使用的缓存。 .NET框架没有提供通用的LRU缓存类,因此我建立了一个,如果需要,可以在这里找到。每次用户访问选项卡页时,我都会将其添加到LRU缓存中。然后,检查窗口把手是否不足。如果是的话,我会丢弃最近使用最少的选项卡页上的控件,并继续这样做,直到再次拥有足够的窗口句柄为止。