【发布时间】:2019-07-26 14:21:31
【问题描述】:
我目前正在编写一个 Windows 服务(作为 LocalSystem 安装),它可以监控 pc/server 上的一些东西,包括进程。对于进程,我正在观察内存使用情况,并“尝试”获取每个进程的 GDI 对象数量(可以在任务管理器中看到)。
遗憾的是,C# Process 对象没有内置 gdi 计数,因此我使用来自“user32.dll”的 GetGuiResources 方法,如下例所示: https://www.pinvoke.net/default.aspx/user32.getguiresources.
基本上我有一个可执行名称列表,对于每个可执行名称,我使用 GetProcessesByName 来检索所有进程实例,然后对于每个唯一进程,我获取句柄并将其发送到函数以获取 Gdi 对象计数。
当我在本地机器上将其作为简单的控制台应用程序(通过 Console.ReadLine 提供名称)尝试时,只要控制台应用程序以管理员身份启动,它就可以正常工作;我得到与任务管理器相同的数字。 但是,当监控服务调用此函数时,我得到 0(返回错误代码 87)或更糟:与服务绑定的进程(无 gui)在任务管理器时返回一些随机数(12、7、4 等)实际上显示 0(最后一个错误 = 0)。
所以总而言之,每个在任务管理器中显示一些 GID 对象的进程都返回 0(错误 87),每个有 0 的进程都返回一个数字(没有错误,或者监控服务本身的错误 183)。
我已经在 Windows 10、Windows Server 2012、Windows Server 2008、Windows Server 2003、Windows Server 2016 上进行了尝试。在 Windows 10(我的机器)上,我到处都是 0,在其他操作系统上,我得到了提到的结果。
这是我使用的代码的简化版本:
// Monitoring processes exeName example: ssms, sqlbrowser
List<Process> result = Process.GetProcessesByName(exeName).ToList();
if (processes != null)
{
for (int i = 0; i < processes.Count; i++)
{
int gdiCount = processes[i].GetGDIObjectsCount(); // extension method
// logging and doing stuff with gdi count here (but i get 0s or random numbers as I told)
}
}
// Process extension method
public static class CProcessExtensions
{
[DllImport("User32", SetLastError = true)]
extern private static int GetGuiResources(IntPtr hProcess, int uiFlags);
private static int GetGDICount(IntPtr processHandle)
{
if (processHandle == IntPtr.Zero)
{
return -1;
}
int count = GetGuiResources(processHandle, 0);
// Logging Marshal.GetLastWin32Error() here
return count;
}
public static int GetGDIObjectsCount(this Process process)
{
IntPtr handle;
process.Refresh();
try
{
handle = process.Handle;
}
catch (Exception ex)
{
handle = IntPtr.Zero;
}
return GetGDICount(handle);
}
}
我也尝试使用 OpenProcess dll 方法获取进程句柄,但结果相同。 以前有人遇到过这种问题吗?
【问题讨论】:
-
这确实似乎相关,可以解释我一直遇到的问题,不知道服务在一个孤立的会话中运行。我要进行更多测试。