在 C# 中终止进程时,我如何确定我正在终止正确的进程?
When killing a process in C#, how can I be sure I'm killing the right one?
总体目标
我正试图终止我当前拥有的某个名称(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();
}
是的,有杀错进程的风险。 PID的重用大概是一个历史事故,多年来引起了很多悲痛。
这样做:
- 找到您要杀死的 PID。
- 获取这些进程的句柄以稳定 PID。请注意,这可能会获得 错误的 进程的句柄。
- 重新找到您要杀死的 PID。
- 杀死那些你已经稳定的并且在第二个查找结果集中的进程。
通过插入这个锁定和验证步骤,您可以确定。
从我获取一个 PID 到我杀死它的时间,有多大可能产生了另一个使用该 PID 的应用程序?
如果另一个应用程序是在另一个应用程序处于活动状态时生成的,则不会为其分配相同的 PID。所以这种情况不会发生,因为 Windows' PID 是该特定进程的唯一十进制数字。
如果我抓取一个 ID 为 123 的 PID,它可能已经关闭并且另一个应用程序现在拥有 PID 123 的可能性有多大?
这在技术上是可行的,即可以在您获得对进程的处理时间和您想要终止它之间关闭该进程。但是,这将完全取决于代码中流程处理的生命周期。我想总会有应用程序可能会在您即将挂钩时关闭的边缘情况,但如果您正在谈论 milliseconds/a 几秒钟,我想它会很少而且相距甚远。至于 Windows 之后立即分配相同的 PID,我不确定,但它们看起来很随机,现在在使用后立即再次分配,但它们最终会这样做。
在限制我关闭错误 PID 的可能性的同时合理地实现这一目标的最佳方法是什么?
管理事件观察器 class 似乎允许您监视进程的启动和停止。也许这可以用于在您给定的进程名称关闭时捕获事件,这样您就知道它不再存在了?
Another answer discussing Management Event Watcher
考虑相反的方法 - 调整服务帐户的权限,使其不能终止其他用户的进程。
我相信这样的权限非常接近非管理员帐户的默认值(或只是默认值) - 所以除非你 运行 服务作为框 admin/system 你可能没有代码解决方案.
只要进程继续 运行,进程 ID 就保证保持不变。一旦进程退出...就无法保证了。
当新进程启动时,Windows 将随机选择一个进程 ID 并将其分配给新进程。不太可能,但有可能选择的 ID 与最近退出的进程相关联。
你看过System.Diagnostics.Process
了吗?
他们有一个 GetProcessesByName
方法,该方法将 return 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
}
}
总体目标
我正试图终止我当前拥有的某个名称(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();
}
是的,有杀错进程的风险。 PID的重用大概是一个历史事故,多年来引起了很多悲痛。
这样做:
- 找到您要杀死的 PID。
- 获取这些进程的句柄以稳定 PID。请注意,这可能会获得 错误的 进程的句柄。
- 重新找到您要杀死的 PID。
- 杀死那些你已经稳定的并且在第二个查找结果集中的进程。
通过插入这个锁定和验证步骤,您可以确定。
从我获取一个 PID 到我杀死它的时间,有多大可能产生了另一个使用该 PID 的应用程序?
如果另一个应用程序是在另一个应用程序处于活动状态时生成的,则不会为其分配相同的 PID。所以这种情况不会发生,因为 Windows' PID 是该特定进程的唯一十进制数字。
如果我抓取一个 ID 为 123 的 PID,它可能已经关闭并且另一个应用程序现在拥有 PID 123 的可能性有多大?
这在技术上是可行的,即可以在您获得对进程的处理时间和您想要终止它之间关闭该进程。但是,这将完全取决于代码中流程处理的生命周期。我想总会有应用程序可能会在您即将挂钩时关闭的边缘情况,但如果您正在谈论 milliseconds/a 几秒钟,我想它会很少而且相距甚远。至于 Windows 之后立即分配相同的 PID,我不确定,但它们看起来很随机,现在在使用后立即再次分配,但它们最终会这样做。
在限制我关闭错误 PID 的可能性的同时合理地实现这一目标的最佳方法是什么?
管理事件观察器 class 似乎允许您监视进程的启动和停止。也许这可以用于在您给定的进程名称关闭时捕获事件,这样您就知道它不再存在了?
Another answer discussing Management Event Watcher
考虑相反的方法 - 调整服务帐户的权限,使其不能终止其他用户的进程。
我相信这样的权限非常接近非管理员帐户的默认值(或只是默认值) - 所以除非你 运行 服务作为框 admin/system 你可能没有代码解决方案.
只要进程继续 运行,进程 ID 就保证保持不变。一旦进程退出...就无法保证了。
当新进程启动时,Windows 将随机选择一个进程 ID 并将其分配给新进程。不太可能,但有可能选择的 ID 与最近退出的进程相关联。
你看过System.Diagnostics.Process
了吗?
他们有一个 GetProcessesByName
方法,该方法将 return 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
}
}