0

我们有一些有效的代码,但是太慢了。我们使用 System.Management.ManagementObjectSearcher 为“Select * from Win32_Process”运行 ObjectQuery。然后我们迭代返回的列表,调用“GetOwner”(通过 InvokeMethod)来查看进程是否由我们正在搜索的用户执行,并且然后调用“终止”(也通过 InvokeMethod)。

通过一些额外的异常处理来解决在迭代过程中终止的进程,这很有效,但是在我们需要运行它的具有数千个进程的机器上,迭代所有进程需要整整一个小时。

是否有不涉及在目标服务器上占用空间的替代方法?远程部分是我们正在做的事情的关键。如果我们必须去本地,我们可以选择 win32 api,但我想如果在本地运行 WMI 会足够快。

4

2 回答 2

1

不幸的是,如果您想提高性能,WMI 检索进程所有者的速度非常慢,那么您必须使用 WInAPi 函数OpenProcessTokenCloseHandle.

检查这个样本

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Security.Principal;
using System.Runtime.InteropServices;

namespace ConsoleApplicationTest
{
    class Program
    {
        static uint TOKEN_QUERY = 0x0008;

        [DllImport("advapi32.dll", SetLastError = true)]
        static extern bool OpenProcessToken(IntPtr ProcessHandle, UInt32 DesiredAccess, out IntPtr TokenHandle);

        [DllImport("kernel32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool CloseHandle(IntPtr hObject);


        static void Main(string[] args)
        {
            foreach (Process p in Process.GetProcesses())
            {
                IntPtr TokenHandle = IntPtr.Zero;
                try
                {
                    OpenProcessToken(p.Handle, TOKEN_QUERY, out TokenHandle);
                    WindowsIdentity WinIdent = new WindowsIdentity(TokenHandle);
                    Console.WriteLine("Pid {0} Name {1} Owner {2}", p.Handle, p.ProcessName, WinIdent.Name);
                }
                catch (Exception Ex)
                {
                    Console.WriteLine("{0} in {1}", Ex.Message, p.ProcessName);
                }
                finally
                {
                    if (TokenHandle != IntPtr.Zero) { CloseHandle(TokenHandle); }
                }
            }
            Console.ReadKey();
        }
    }
}
于 2012-04-10T20:35:14.193 回答
0

我不确定哪个工作缓慢,迭代或调用方法。我猜应该是后一种吧。

  • 您可以尝试 ManagementClass.GetInstances() 而不是运行 wmi 查询吗?
  • 尝试遍历返回的 WMI 实例并将它们缓存到队列中。然后,您将能够创建多个线程。他们每个人都在队列中选择一个实例并调用方法。
于 2012-04-10T20:18:18.910 回答