繁体   English   中英

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

[英]When killing a process in C#, how can I be sure I'm killing the right one?

总体的目标

我试图通过我目前拥有的某个名称(下面的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();
    }

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

像这样做:

  1. 找到你要杀死的PID。
  2. 获取这些进程的句柄以稳定PID。 请注意,这可能会获得错误进程的句柄。
  3. 重新找到要杀死的PID。
  4. 杀死已稳定且位于第二个查找结果集中的进程。

通过插入此锁定和验证步骤,您可以确定。

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

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

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

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

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

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

另一个答案讨论管理事件观察者

具有示例用法的MSDN ManagementEventWatcher类

考虑相反的方法 - 调整服务帐户的权限,以便它不会杀死其他用户的进程。

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

只要进程继续运行,进程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
   }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM