如何在.NET中获取当前的窗口句柄计数和窗口句柄限制?
我想获取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缓存中。然后,检查窗口把手是否不足。如果是的话,我会丢弃最近使用最少的选项卡页上的控件,并继续这样做,直到再次拥有足够的窗口句柄为止。