Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/285.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从进程id/对象获取进程实例名称(更快的方法)_C# - Fatal编程技术网

C# 从进程id/对象获取进程实例名称(更快的方法)

C# 从进程id/对象获取进程实例名称(更快的方法),c#,C#,目前,从进程ID获取实例名称的解决方案来自下面的代码。 问题是,这需要大量的时间和CPU资源 也就是说,当您有一个运行至少100个进程的系统时,通过循环找到它需要相当长的时间。(比如1到2秒)当我想找到其中的30个进程时,需要30秒才能找到所有进程 您不能简单地从流程对象获取实例名称吗 private static string GetProcessInstanceName(int pid) { PerformanceCounterCategory cat = new Performance

目前,从进程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 ...");
}

为什么不使用
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));
}