我在这里听到答案:
并实施了他所说的一切。我的监视器初始化如下:
netSentCounter.CategoryName = ".NET CLR Networking";
netSentCounter.CounterName = "Bytes Sent";
netSentCounter.InstanceName = Misc.GetInstanceName();
netSentCounter.ReadOnly = true;
我可以正确地看到Misc.GetInstanceName()
返回“MyProcessName [id]”。但是,我不断得到实例在指定类别中不存在的异常。
我的理解是,在您实际发送或接收之前,不会创建网络发送/接收的类别。
我已按照答案中所述添加了app.config,如下所示:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.net>
<settings>
<performanceCounters enabled="true" />
</settings>
</system.net>
</configuration>
为什么我仍然会收到错误?
这是我的监控代码:
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;
}
}
编辑:我已从Windows打开资源监视器以查看问题所在。虽然设置了app.config,但计数器仍未启动。
这就是我所看到的(这是我的应用程序发送网络活动之前和之后)
并且名称不是我的方法返回的名称。我的方法返回“SuperScraper [appId]”,而在资源中它被称为“Superscraper.vshost.exe”。
所以我现在有两个问题:
- 我的计数器没有在应用启动时启动 - 这个名字是不同的
答案 0 :(得分:4)
好的,我终于明白了。列出的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]
_ {广告{1}}
希望这能节省一些时间!!
答案 1 :(得分:1)
好的,我试过你的例子。我还看到了在性能监视器中没有显示的计数器,但在我更改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()
)计数器。