简体   繁体   中英

Problem working with the NetworkInterface.Name

I am using following code to detect the name of the Network Interface Card on my PC. I am using a USB Modem.

public class DetectNIC
{
    public string ReturnNIC()
    {
        List<NetworkInterface> Interfaces = new List<NetworkInterface>();
        foreach (var nic in NetworkInterface.GetAllNetworkInterfaces())
        {
            if (nic.OperationalStatus == OperationalStatus.Up)
            {
                Interfaces.Add(nic);
            }
        }

        NetworkInterface result = null;
        foreach (NetworkInterface nic in Interfaces)
        {
            if (result == null)
            {
                result = nic;
            }
            else
            {
                if (nic.GetIPProperties().GetIPv4Properties() != null)
                {
                    if (nic.GetIPProperties().GetIPv4Properties().Index < result.GetIPProperties().GetIPv4Properties().Index)
                        result = nic;
                }
            }
        }
        return result.Name.ToString();
    }
}

I am passing the result to the below given class to calculate the bytes consumption during internet traffic:

public class ByteCounter
{
    public double GetNetworkUtilization(string networkCard)
    {
        const int numberOfIterations = 10;

        PerformanceCounter bandwidthCounter =
            new PerformanceCounter("Network Interface", "Current Bandwidth", networkCard);

        float bandwidth = bandwidthCounter.NextValue();

        PerformanceCounter dataSentCounter =
            new PerformanceCounter("Network Interface", "Bytes Sent/sec", networkCard);

        PerformanceCounter dataReceivedCounter =
            new PerformanceCounter("Network Interface", "Bytes Received/sec", networkCard);

        float sendSum = 0;
        float receiveSum = 0;

        for (int index = 0; index < numberOfIterations; index++)
        {
            sendSum += dataSentCounter.NextValue();
            receiveSum += dataReceivedCounter.NextValue();
        }

        float dataSent = sendSum;
        float dataReceived = receiveSum;

        double utilization = (8 * (dataSent + dataReceived)) / (bandwidth * numberOfIterations) * 100;
        return utilization;
    }
}

The first code works fine. It detects my modem as "MBlaze USB Modem", but when the control reaches to the second code with following line:

float bandwidth = bandwidthCounter.NextValue();

it displays error:

System.InvalidOperationException was unhandled
  Message="Instance 'MBlaze USB Modem' does not exist in the specified Category."
  Source="System"
  StackTrace:
       at System.Diagnostics.CounterDefinitionSample.GetInstanceValue(String instanceName)
       at System.Diagnostics.PerformanceCounter.NextSample()
       at System.Diagnostics.PerformanceCounter.NextValue()
       at LogTraffic.ByteCounter.GetNetworkUtilization(String networkCard) in F:\Projects\LogTraffic\bytecounter.cs:line 15
       at LogTraffic.MainForm.MainForm_Load(Object sender, EventArgs e) in F:\Projects\LogTraffic\MainForm.cs:line 24
       at System.Windows.Forms.Form.OnLoad(EventArgs e)
       at System.Windows.Forms.Form.OnCreateControl()
       at System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
       at System.Windows.Forms.Control.CreateControl()
       at System.Windows.Forms.Control.WmShowWindow(Message& m)
       at System.Windows.Forms.Control.WndProc(Message& m)
       at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
       at System.Windows.Forms.ContainerControl.WndProc(Message& m)
       at System.Windows.Forms.Form.WmShowWindow(Message& m)
       at System.Windows.Forms.Form.WndProc(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
       at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
       at System.Windows.Forms.SafeNativeMethods.ShowWindow(HandleRef hWnd, Int32 nCmdShow)
       at System.Windows.Forms.Control.SetVisibleCore(Boolean value)
       at System.Windows.Forms.Form.SetVisibleCore(Boolean value)
       at System.Windows.Forms.Control.set_Visible(Boolean value)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.Run(Form mainForm)
       at LogTraffic.Program.Main() in F:\Projects\LogTraffic\Program.cs:line 18
       at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: 

What is the problem?

I won't forget to give the credit to the authors of both the code.

First code credit: Keyvan Nayyeri

Second code credit: entens for his answer here .

I modified my NIC finding code to return result.Description instead of result.Name . This should give the full interface name used as the InstanceName.

Windows will replace special characters however, so you should be aware of that. Which may be found at the MSDN page for the PerformanceCounter.InstanceName property.

I also made some modifications to the code from Keyvan Nayyeri to condition the input string to match expected instance names. Also, I incorporated Aliostad's code for searching the category for a matching name, but I only throw an exception if the InstanceName does not exist.

    public double GetNetworkUtilization(string networkCard)
{
    const int numberOfIterations = 10;

    // Condition networkCard;
    networkCard = networkCard.Replace("\\", "_");
    networkCard = networkCard.Replace("/", "_");
    networkCard = networkCard.Replace("(", "[");
    networkCard = networkCard.Replace(")", "]");
    networkCard = networkCard.Replace("#", "_");

    PerformanceCounterCategory NetworkInterfaceCatagory =
        PerformanceCounterCategory.GetCategories().Where(c => c.CategoryName.Equals("Network Interface")).FirstOrDefault();

    //// DEBUG: Check this array to see if the network card exists 
    //foreach(string instance in NetworkInterfaceCatagory.GetInstanceNames())
    //{
    //    System.Diagnostics.Debug.Print(instance);
    //}

    if (string.IsNullOrEmpty(NetworkInterfaceCatagory.GetInstanceNames().Where(i => i.Equals(networkCard)).FirstOrDefault()))
        throw new ApplicationException("NIC does not exist in existing performance counters");

    string instanceName = networkCard;

    PerformanceCounter bandwidthCounter =
        new PerformanceCounter("Network Interface", "Current Bandwidth", instanceName);

    PerformanceCounter dataSentCounter =
        new PerformanceCounter("Network Interface", "Bytes Sent/sec", instanceName);

    PerformanceCounter dataReceivedCounter =
        new PerformanceCounter("Network Interface", "Bytes Received/sec", instanceName);

    float bandwidth = bandwidthCounter.NextValue();
    float sendSum = 0;
    float receiveSum = 0;

    for (int index = 0; index < numberOfIterations; index++)
    {
        sendSum += dataSentCounter.NextValue();
        receiveSum += dataReceivedCounter.NextValue();
    }

    float dataSent = sendSum;
    float dataReceived = receiveSum;

    double utilization = (8 * (dataSent + dataReceived)) / (bandwidth * numberOfIterations) * 100;
    return utilization;
}

Your problem is that the instance name is a bit different from the name you get from the ReturnNIC and you are using netwrokCard in all places. I have modified the code a bit and now it works for me:

    public static double GetNetworkUtilization(string networkCard)
    {
        const int numberOfIterations = 10;
        PerformanceCounterCategory category = null;
        foreach (var performanceCounterCategory in PerformanceCounterCategory.GetCategories())
        {
            if (performanceCounterCategory.CategoryName == "Network Interface")
            {
                category = performanceCounterCategory;
                break;
            }
        }

        string instanceName = category.GetInstanceNames().Where(x=>x.Contains(networkCard)).FirstOrDefault();

        PerformanceCounter bandwidthCounter =
            new PerformanceCounter("Network Interface", "Current Bandwidth", instanceName);

        float bandwidth = bandwidthCounter.NextValue();

        PerformanceCounter dataSentCounter =
            new PerformanceCounter("Network Interface", "Bytes Sent/sec", instanceName);

        PerformanceCounter dataReceivedCounter =
            new PerformanceCounter("Network Interface", "Bytes Received/sec", instanceName);

        float sendSum = 0;
        float receiveSum = 0;

        for (int index = 0; index < numberOfIterations; index++)
        {
            sendSum += dataSentCounter.NextValue();
            receiveSum += dataReceivedCounter.NextValue();
        }

        float dataSent = sendSum;
        float dataReceived = receiveSum;

        double utilization = (8 * (dataSent + dataReceived)) / (bandwidth * numberOfIterations) * 100;
        return utilization;
    }

According to the code presented at MSDN system.diagnostics.performancecounter.nextvalue

    // If the category does not exist, create the category and exit.
    // Performance counters should not be created and immediately used.
    // There is a latency time to enable the counters, they should be created
    // prior to executing the application that uses the counters.
    // Execute this sample a second time to use the category.

It does not appear that you are creating the category nor waiting a duration of time for the performance counter to collect data prior to reading data.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM