C# 从进程id/对象获取进程实例名称(更快的方法)
目前,从进程ID获取实例名称的解决方案来自下面的代码。 问题是,这需要大量的时间和CPU资源 也就是说,当您有一个运行至少100个进程的系统时,通过循环找到它需要相当长的时间。(比如1到2秒)当我想找到其中的30个进程时,需要30秒才能找到所有进程 您不能简单地从流程对象获取实例名称吗C# 从进程id/对象获取进程实例名称(更快的方法),c#,C#,目前,从进程ID获取实例名称的解决方案来自下面的代码。 问题是,这需要大量的时间和CPU资源 也就是说,当您有一个运行至少100个进程的系统时,通过循环找到它需要相当长的时间。(比如1到2秒)当我想找到其中的30个进程时,需要30秒才能找到所有进程 您不能简单地从流程对象获取实例名称吗 private static string GetProcessInstanceName(int pid) { PerformanceCounterCategory cat = new Performance
private static string GetProcessInstanceName(int pid)
{
PerformanceCounterCategory cat = new PerformanceCounterCategory("Process");
string[] instances = cat.GetInstanceNames();
foreach (string instance in instances)
{
using (PerformanceCounter cnt = new PerformanceCounter("Process",
"ID Process", instance, true))
{
int val = (int) cnt.RawValue;
if (val == pid)
{
return instance;
}
}
}
throw new Exception("Could not find performance counter " +
"instance name for current process. This is truly strange ...");
}
为什么不使用
System.Diagnostics.Process.GetProcessById
函数
private static string GetProcessInstanceName(int pid)
{
string name = String.Empty;
Process proc = System.Diagnostics.Process.GetProcessById(pid);
if(proc != null)
{
name = proc.ProcessName;
}
return name;
}
这将使您了解所有当前流程
var allProcesses = System.Diagnostics.Process.GetProcesses();
然后,您可以在数组中进行迭代,以找到要查找的特定id。一个非常快速且有效的解决方案是:
public static string GetInstanceNameForProcessId(int processId)
{
var process = Process.GetProcessById(processId);
string processName = Path.GetFileNameWithoutExtension(process.ProcessName);
PerformanceCounterCategory cat = new PerformanceCounterCategory("Process");
string[] instances = cat.GetInstanceNames()
.Where(inst => inst.StartsWith(processName))
.ToArray();
foreach (string instance in instances)
{
using (PerformanceCounter cnt = new PerformanceCounter("Process",
"ID Process", instance, true))
{
int val = (int)cnt.RawValue;
if (val == processId)
{
return instance;
}
}
}
return null;
}
从。我唯一的问题与他博客上的评论相同:
需要提及的一件事与windows进程实例有关
名称是指当其中一个进程退出时,名称会动态更改
例如,如果chrome#8退出,chrome#9将变成chrome#8,并且
铬#10
将变成铬9。此时获取计数器的值
以前为chrome#10创建的浏览器将抛出异常。这是
如果您想监视多个
在监控流程出口和
重新创建所有计数器(非常难看)
一种方法是更改流程实例名称的使用方式
已生成(请参阅),但此已生成
可能影响使用perfmon api的其他应用程序
通过只查看以相关流程名称开头的流程,可以加快原始流程的速度。除此之外的一个改进是使用PLINQ(并行LINQ)。或者,Parallel.ForEach()
或使用Task
的构造可以提供类似的加速,但这两种构造都有复杂的源代码,只返回第一个找到的,并取消并行搜索(通过ParallelEnumerable.FirstOrDefault()
很好地隐藏)
公共静态字符串PerformanceCounterInstanceName(此进程)
{
var matchesProcessId=newfunc(instanceName=>
{
使用(var pc=新的PerformanceCounter(“进程”、“ID进程”、instanceName、true))
{
if((int)pc.RawValue==process.Id)
{
返回true;
}
}
返回false;
});
字符串processName=Path.GetFileNameWithoutExtension(process.processName);
返回新的PerformanceCounterCategory(“流程”)
.GetInstanceNames()
.天冬酰胺()
.FirstOrDefault(instanceName=>instanceName.StartsWith(processName)
&&matchesProcessId(instanceName));
}
问题是,如果同一个nname有多个实例,例如:java#1 java#2,它不会返回正确的进程号。。仅限java。@user3289302您无法获得比进程id
更具体的信息。如果您得到它,它肯定会返回带有该pid的1(也是唯一一个)进程。PerformanceCounter方法需要instanceName而不是pid…如下所示:new PerformanceCounter(“进程”,“处理器时间”,“instanceName”);如果只有1个同名实例在运行,则上述函数可以正常工作,但如果有2个同名实例,则方法不会像performanceCounter预期的那样返回该函数。。你知道其他的方法吗?或者,是否有一种方法可以用pid代替PerformanceCounter?@@user3289302您的问题我弄错了吗?如果是,我很抱歉。根据函数名(GetProcessInstanceName
)和函数中实现的逻辑,似乎您正试图通过其Id获取进程名。如果我是正确的,您可以使用我的函数而不是您的函数,并且不需要PerformanceCounter
。
public static string PerformanceCounterInstanceName(this Process process)
{
var matchesProcessId = new Func<string, bool>(instanceName =>
{
using (var pc = new PerformanceCounter("Process", "ID Process", instanceName, true))
{
if ((int)pc.RawValue == process.Id)
{
return true;
}
}
return false;
});
string processName = Path.GetFileNameWithoutExtension(process.ProcessName);
return new PerformanceCounterCategory("Process")
.GetInstanceNames()
.AsParallel()
.FirstOrDefault(instanceName => instanceName.StartsWith(processName)
&& matchesProcessId(instanceName));
}