2012-04-17 71 views
0

我在这里以下答案:缺少网络发送/接收

Calculating Bandwidth

而且他说的那样实现一切。我的显示器被初始化像这样:

netSentCounter.CategoryName = ".NET CLR Networking"; 
netSentCounter.CounterName = "Bytes Sent"; 
netSentCounter.InstanceName = Misc.GetInstanceName(); 
netSentCounter.ReadOnly = true; 

我可以corrently看到Misc.GetInstanceName()返回 “MyProcessName [ID]”。但是,我一直在获取例外情况,即该实例不存在于指定的类别中。

我的理解是,发送/接收的网络类别不会在您实际发送或接收之前创建。

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
    <system.net> 
     <settings> 
      <performanceCounters enabled="true" /> 
     </settings> 
    </system.net> 
</configuration> 

为什么我仍然得到一个错误:

像这样的答案描述我已经添加了的app.config?

这里是我的监管码:

public static class Monitoring 
{ 
    private static PerformanceCounter netSentCounter = new PerformanceCounter(); 

    //Static constructor 
    static Monitoring() 
    { 
     netSentCounter.CategoryName = ".NET CLR Networking"; 
     netSentCounter.CounterName = "Bytes Sent"; 
     netSentCounter.InstanceName = Misc.GetInstanceName(); 
     netSentCounter.ReadOnly = true; 
    } 

    /// <summary> 
    /// Returns the amount of data sent from the current application in MB 
    /// </summary> 
    /// <returns></returns> 
    public static float getNetSent() 
    { 
     return (float)netSentCounter.NextValue()/1048576; //Convert to from Bytes to MB 
    } 
} 

我的杂项类:

public static class Misc 
{ 

    //Returns an instance name 
    internal static string GetInstanceName() 
    { 
     // Used Reflector to find the correct formatting: 
     string assemblyName = GetAssemblyName(); 
     if ((assemblyName == null) || (assemblyName.Length == 0)) 
     { 
      assemblyName = AppDomain.CurrentDomain.FriendlyName; 
     } 
     StringBuilder builder = new StringBuilder(assemblyName); 
     for (int i = 0; i < builder.Length; i++) 
     { 
      switch (builder[i]) 
      { 
       case '/': 
       case '\\': 
       case '#': 
        builder[i] = '_'; 
        break; 
       case '(': 
        builder[i] = '['; 
        break; 

       case ')': 
        builder[i] = ']'; 
        break; 
      } 
     } 
     return string.Format(CultureInfo.CurrentCulture, 
          "{0}[{1}]", 
          builder.ToString(), 
          Process.GetCurrentProcess().Id); 
    } 

    /// <summary> 
    /// Returns an assembly name 
    /// </summary> 
    /// <returns></returns> 
    internal static string GetAssemblyName() 
    { 
     string str = null; 
     Assembly entryAssembly = Assembly.GetEntryAssembly(); 
     if (entryAssembly != null) 
     { 
      AssemblyName name = entryAssembly.GetName(); 
      if (name != null) 
      { 
       str = name.Name; 
      } 
     } 
     return str; 
    } 
} 

编辑:我从窗户打开资源监视器,看看是什么问题。计数器不会启动,尽管app.config设置为这样做。

这是我所看到的(在此之前和之后我的应用程序发送的网络活动)

enter image description here

和名字是不是我的方法是返回。我的方法返回“SuperScraper [appId]”,而在资源中它被称为“Superscraper.vshost.exe”。

所以我现在有两个问题:

-My计数器没有启动应用程序启动时 -The的名字是目前存在的

+0

你能显示堆栈跟踪吗?什么是杂项? [Here](http://pastebin.com/f371375d6)是全部代码,只是复制粘贴。 – Reniuz 2012-04-17 09:36:36

+0

杂项只是我使用的图书馆。我会发布堆栈跟踪。 – TheGateKeeper 2012-04-17 09:40:23

+1

调用堆栈非常空。它所做的就是从我的库中调用该方法。问题是因为代码位于库中而不是我的主应用程序中?我的代码非常像你的代码。 – TheGateKeeper 2012-04-17 09:42:07

回答

1

好吧,我想你的例子。我也expierenced该计数器didnt性能监视器中显示,但它确实我改变ReadOnly后,并设置RawValue属性:

netSentCounter.CategoryName = ".NET CLR Networking"; 
netSentCounter.CounterName = "Bytes Sent"; 
netSentCounter.InstanceName = Misc.GetInstanceName(); 
netSentCounter.ReadOnly = false; //<== 
netSentCounter.RawValue = 0;  //<== 

在我的情况,我发现在性能监视器实例名称的格式如下:myapplicationname_pPID

所以以后我在你GetInstanceName方法直线变更

return string.Format(CultureInfo.CurrentCulture, 
         "{0}[{1}]", 
         builder.ToString(), 
         Process.GetCurrentProcess().Id); 

return string.Format(CultureInfo.CurrentCulture, 
        "{0}_p{1}",     
        builder.ToString().ToLower(), //<== dont miss ToLower() 
        Process.GetCurrentProcess().Id); 

计数器看起来像开始工作。

下面是引用如何add and remove counter instance

想想也删除(netSentCounter.RemoveInstance())计数器完成使用它后。

+0

我真的不知道它有什么问题。我已经设法使用您的代码创建它,但它永远不会返回任何内容。它所做的就是让我回到0。如果我不自己创建它,它确实会返回值。你认为这是因为'netSentCounter.RawValue = 0;'?你的回报值了吗? – TheGateKeeper 2012-04-17 13:31:50

+0

以及我没有测试过,我只是想弄清楚为什么你会得到错误。 – Reniuz 2012-04-17 14:06:52

+0

名称匹配,我创建它在同一个地方,但值永远不会改变。如果我不创建它并让它自己创建(例如通过发送请求),它会报告值。你可以测试你是否得到相同的行为? – TheGateKeeper 2012-04-17 16:30:20

3

好吧,我终于明白了。列出的步骤Calculating Bandwidth似乎已过时,并且不再适用于.Net 4.

我将解释整个过程,以便您可以做到这一点。

首先,你需要添加到您的app.config:

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
    <system.net> 
     <settings> 
      <performanceCounters enabled="true" /> 
     </settings> 
    </system.net> 
</configuration> 

.NET 4.0之前,本作的应用程序中创建启动时的计数器(而不是例如,创建网络计数器时你的应用程序发送一个请求)。在.Net 4.0中,这告诉它在使用它们时创建计数器。 IE浏览器。如果你不设置这个,将不会创建任何计数器。

现在,这是我浪费大部分时间的地方。我错误地认为,如果你创建一个性能计数器,其名称与自然创建的名称相同,你将得到这些值。但是,这一切都阻止了真正的柜台出现。

所以这样做:

//In .Net 4.0 the category is called .NET CLR Networking 4.0.0.0 and not .NET CLR Networking 
netSentCounter.CategoryName = ".NET CLR Networking 4.0.0.0"; 
netSentCounter.CounterName = "Bytes Sent"; 
netSentCounter.InstanceName = Misc.GetInstanceName(); 
netSentCounter.ReadOnly = false; //<== 
netSentCounter.RawValue = 0;  //<== 

简单的块真正的计数器。

你需要做的是以自然的方式启动它。要做到这一点,最好的方法是简单地将在应用程序启动恶搞请求,然后“倾听”使用性能计数器:

//Send spoof request here 
netSentCounter.CategoryName = ".NET CLR Networking 4.0.0.0"; 
netSentCounter.CounterName = "Bytes Sent"; 
netSentCounter.InstanceName = Misc.GetInstanceName(); 
netSentCounter.ReadOnly = true; 

最后一点。实例名称不再是ApplicationName[appId]。现在是:

[ApplicationName] .exe_p [appId] _r [the CLR id hosting your application] _AD [ApplicationDomain]

希望这样可以节省别人的时间!

+0

Upvote for“在.Net 4.0中,它告诉它在使用时创建计数器”。谢谢:) – Henners 2014-11-10 12:21:13

+0

顺便说一句,这里是获取.NET性能计数器的完整实例名称的正确方法:http://stackoverflow.com/questions/10196432/getting-the-clr-id – Funbit 2015-03-06 16:26:25