在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的可能性的最佳方法是什么李>
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。所以这种情况不会发生,因为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属性。”我需要做一些调查,弄清楚这到底意味着什么。。。当我完全理解答案时,我会更新它。这是一个有趣的方法,我会考虑它。我们的服务目前确实增加了一些权限,但如果正确锁定,这可能是一个更简单的解决方案。我仍然认为我希望我的代码能够对自己的行为负责,因为使用错误的权限可能会造成一些不良影响;我最初是这样想的。这似乎是一个可以消除(公认已经很小)问题发生的可能性的答案