在C#中杀死进程时,我怎么能确定我正在杀死正确的进程?

时间:2015-01-29 21:19:24

标签: c# process wmi

总体目标

我试图通过我目前拥有的某个名称(下面notepad.exe)来杀死所有进程。一般来说,它的顺序如下:

  • 获取具有我所有权的特定名称的所有应用程序
    • 在这种情况下,"我"通常是服务帐户
  • 杀死所有人。

问题

  • 从我获取PID到杀死它的时间,有多少可能会产生另一个使用该PID的应用程序?如果我获取ID为123的PID,它有多大可能关闭,而另一个应用程序现在拥有PID 123?
  • 在限制我杀掉错误的PID的可能性的同时,我可以合理地解决这个问题的最佳方法是什么?

我到目前为止

以下代码基于另一个SO答案,并使用WMI按特定名称获取所有流程并列出用户。

下一步:下一步是杀死我拥有的进程;但是,我如何判断我在这里的PID将与我试图杀死的PID相同?

static void Main(string[] args)
    {
        const string PROCESS_NAME = "notepad.exe";
        var queryString = string.Format("Name = '{0}'", PROCESS_NAME);

        var propertiesToSelect = new[] { "Handle", "ProcessId" };
        var processQuery = new SelectQuery("Win32_Process", queryString, propertiesToSelect);

        using (var searcher = new ManagementObjectSearcher(processQuery))
        {
            using (var processes = searcher.Get())
                foreach (var aProcess in processes)
                {
                    var process = (ManagementObject)aProcess;
                    var outParameters = new object[2];
                    var result = (uint)process.InvokeMethod("GetOwner", outParameters);

                    if (result == 0)
                    {
                        var user = (string)outParameters[0];
                        var domain = (string)outParameters[1];
                        var processId = (uint)process["ProcessId"];

                        Console.WriteLine("PID: {0} | User: {1}\\{2}", processId, domain, user);
                        // TODO: Use process data...
                    }
                    else
                    {
                        // TODO: Handle GetOwner() failure...
                    }
                }

        }

        Console.ReadLine();
    }

4 个答案:

答案 0 :(得分:4)

是的,存在杀死错误进程的风险。重复使用PID可能是历史事故,多年来引起了很多悲痛。

这样做:

  1. 找到要杀死的PID。
  2. 获取这些进程的句柄以稳定PID。请注意,这可能会获得错误的进程的句柄。
  3. 重新找到要杀死的PID。
  4. 终止那些已稳定且位于第二个查找结果集中的流程。
  5. 通过插入此锁定和验证步骤,您可以确定。

答案 1 :(得分:3)

从我获取PID到杀死它的时间有多大可能,另一个应用程序可能会产生使用该PID?

如果另一个应用程序在另一个应用程序处于活动状态时生成,则不会为其分配相同的PID。所以这种情况不会发生在Windows' PID是特定过程的唯一十进制数。

如果我获取ID为123的PID,它有多大可能关闭,而另一个应用程序现在拥有PID 123?

这在技术上是可行的,可以在您获得对该进程的处理与您想要终止该进程之间关闭该进程。但是,这完全取决于代码中进程处理的生命周期。我想总会有一些边缘情况,应用程序可能会被关闭,就像你要挂钩它一样,但是如果你说毫秒/几秒钟,我想它会很少而且很远。至于Windows之后立即分配相同的PID,我不确定,但它们看起来很随机,现在在使用后立即再次分配,但最终会这样做。

在限制我杀掉错误PID的可能性的同时,我可以合理地解决这个问题的最佳方式是什么?

管理事件观察器类似乎允许您监视进程的启动和停止。也许这可以用来捕获事件,只要它们关闭给你的给定进程名称,所以这样你知道它不再存在?

Another answer discussing Management Event Watcher

MSDN ManagementEventWatcher class with example usage

答案 2 :(得分:1)

考虑相反的方法 - 调整服务帐户的权限,使无法杀死其他用户的进程。

我相信这些权限非常接近非管理员帐户的默认值(或者只是默认值) - 因此,除非您以管理员/系统方式运行服务,否则您可以使用无代码解决方案。

答案 3 :(得分:1)

只要进程继续运行,进程ID就保证保持不变。一旦流程退出......就无法保证。

当新进程启动时,Windows将选择一个随机进程ID并将其分配给新进程。它不太可能,但可能选择的id与最近退出的过程有关。

你看过System.Diagnostics.Process吗?

他们有一个GetProcessesByName方法,它将返回一个Process对象列表。

Process [] localByName = Process.GetProcessesByName("notepad");

然后你可以简单地遍历进程并杀死它们。由于Process对象具有进程的句柄...尝试终止它将生成一个有用的异常,您可以捕获它。

foreach (Process p in localByName)
{
   try
   {
        p.Kill();
   }
   catch (Exception e)
   {
       // process either couldn't be terminated or was no longer running
   }
}
相关问题