目前,从进程ID获取实例名称的解决方案来自以下代码。 问题是,这需要大量的时间和CPU资源!
也就是说,当您的系统运行至少100个进程时,需要花费大量时间循环遍历循环才能找到它。 (比如1到2秒)当我想要找到多达30个这样的过程时,最多需要30秒才能找到它们......
您不能简单地从流程对象中获取实例名称吗?
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 ...");
}
答案 0 :(得分:1)
FranzHuber23 Solution仅通过查看以问题进程名称开头的进程来加快了原始速度。除此之外,还有一个改进使用PLINQ(并行LINQ)。可选地,Parallel.ForEach()
或使用Task
的构造可以提供类似的加速,但是这两个都将具有复杂的源,以仅返回第一个找到的内容并取消并发搜索(被ParallelEnumerable.FirstOrDefault()
很好地隐藏了)
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));
}
答案 1 :(得分:0)
这应该可以为您提供所有当前流程
var allProcesses = System.Diagnostics.Process.GetProcesses();
然后您可以遍历数组以查找您要查找的特定ID
答案 2 :(得分:0)
这是一个非常快速且运作良好的解决方案:
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;
}
来自Rick Strahl的。我唯一的问题与他博客评论中的问题相同:
有一点要提到与windows流程实例有关 名称是当其中一个进程退出时它们动态变化。
例如,如果镀铬#8退出,则镀铬#9将变为镀铬#8和 铬#10
将成为chrome#9。此时获取计数器的值 以前为chrome#10创建的将抛出异常。这是 如果你想监视多个实例,真的很烦人 多个流程,因为它涉及监控流程退出和 重新创建所有计数器(非常难看)。
一种方法是更改流程实例名称的方式 生成(见http://support.microsoft.com/kb/281884),但这有 使用perfmon api影响其他应用程序的可能性。
答案 3 :(得分:-1)
为什么不使用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;
}