在C#中终止进程时,如何确保我';我杀对人了? 总体目标

在C#中终止进程时,如何确保我';我杀对人了? 总体目标,c#,process,wmi,C#,Process,Wmi,我正试图以我当前拥有的某个名称(notepad.exe)杀死所有进程。总的来说,它大致是这样的: 获取所有具有我所拥有的特定名称的应用程序 在这种情况下,“I”通常是一个服务帐户 把他们都杀了 问题 从我抓取一个PID到我杀死它的时候,另一个使用该PID的应用程序可能已经产生了,这种可能性有多大?如果我抓取一个ID为123的PID,它关闭的可能性有多大,而另一个应用程序现在拥有PID 123 我可以合理地实现这一点,同时限制我消除错误PID的可能性的最佳方法是什么 到目前为止我所拥有

我正试图以我当前拥有的某个名称(
notepad.exe
)杀死所有进程。总的来说,它大致是这样的:

  • 获取所有具有我所拥有的特定名称的应用程序
    • 在这种情况下,“I”通常是一个服务帐户
  • 把他们都杀了
问题
  • 从我抓取一个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();
    }

是的,存在扼杀错误流程的风险。PIDs的重用可能是一个历史性的意外,多年来造成了很多悲伤

这样做:

  • 找到你想杀死的PID
  • 获取这些进程的句柄以稳定PID。请注意,这可能会获得错误进程的句柄
  • 重新找到你想杀死的PID
  • 杀死那些你已经稳定并且在第二个查找结果集中的进程

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

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

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

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

    这在技术上是可行的,即在您获得流程控制权和想要终止流程之间,流程可以关闭。但是,这将完全取决于代码中处理进程的生命周期。我想总会有一些边缘情况,应用程序可能会在您即将连接到它时关闭,但如果您说的是毫秒/几秒钟,我想这将是很少的。至于Windows在使用后立即分配相同的PID,我不确定,但它们看起来非常随机,现在在使用后立即重新分配,但最终会这样做

    在限制我消除错误PID的可能性的同时,合理实现这一点的最佳方法是什么?

    有一个管理事件观察程序类,它似乎允许您监视进程的启动和停止。也许这可以用来捕获事件,只要它们是为您给定的进程名关闭的,这样您就知道它不再存在了


    考虑相反的方法-调整服务帐户的权限,使其不会终止其他用户的进程


    我相信,对于非管理员帐户,这种权限非常接近默认权限(或者只是默认权限)——因此,除非您以box admin/system的身份运行服务,否则您可能没有代码解决方案。

    只要进程继续运行,进程id就保证保持不变。一旦进程退出。。。没有保证

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

    你看过吗

    它们有一个方法,可以返回进程对象列表

    Process [] localByName = Process.GetProcessesByName("notepad");
    
    然后,您可以简单地遍历这些进程并杀死它们。由于流程对象具有流程的句柄。。。试图杀死它将生成一个有用的异常,您可以捕获它

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

    你打算在取回和杀戮之间有多长时间?另见。帕特里克霍夫曼说:“所以有重复使用的风险,一秒钟,也许更多。”。我的想法是立即获得所有我拥有的名字,然后杀死它们。我们有一个服务,需要关闭一个控制台应用程序,并正在试验在同一台机器上运行不同用户的重复服务。我不想让他们每个人都杀掉其他人的控制台应用。谢谢你的参与!这将是最简单的,除了在本例中,我在该服务器上有两个代码相同的服务,每个服务作为单独的用户运行。所以我让app.exe作为user1运行,app.exe作为user2运行。我只需要关闭以user1身份运行的app.exe进程。是否真的保证这些进程对象具有打开的句柄?上次我看的时候,有一些懒惰的初始化代码。据我所知,GetProcessesByName没有获得句柄。@usr捕捉得很好。。。从文档中。。。“只有通过调用Start启动的进程才能设置相应进程实例的Handle属性。”我需要做一些调查,弄清楚这到底意味着什么。。。当我完全理解答案时,我会更新它。这是一个有趣的方法,我会考虑它。我们的服务目前确实增加了一些权限,但如果正确锁定,这可能是一个更简单的解决方案。我仍然认为我希望我的代码能够对自己的行为负责,因为使用错误的权限可能会造成一些不良影响;我最初是这样想的。这似乎是一个可以消除(公认已经很小)问题发生的可能性的答案