Retrieve process network usage

23,240

Solution 1

Resource monitor uses ETW - thankfully, Microsoft have created a nice nuget .net wrapper to make it easier to use.

I wrote something like this recently to report back my process's network IO:

using System;
using System.Diagnostics;
using System.Threading.Tasks;
using Microsoft.Diagnostics.Tracing.Parsers;
using Microsoft.Diagnostics.Tracing.Session;

namespace ProcessMonitoring
{
    public sealed class NetworkPerformanceReporter : IDisposable
    {
        private DateTime m_EtwStartTime;
        private TraceEventSession m_EtwSession;

        private readonly Counters m_Counters = new Counters();

        private class Counters
        {
            public long Received;
            public long Sent;
        }

        private NetworkPerformanceReporter() { }

        public static NetworkPerformanceReporter Create()
        {
            var networkPerformancePresenter = new NetworkPerformanceReporter();
            networkPerformancePresenter.Initialise();
            return networkPerformancePresenter;
        }

        private void Initialise()
        {
            // Note that the ETW class blocks processing messages, so should be run on a different thread if you want the application to remain responsive.
            Task.Run(() => StartEtwSession()); 
        }

        private void StartEtwSession()
        {
            try
            {
                var processId = Process.GetCurrentProcess().Id;
                ResetCounters();

                using (m_EtwSession = new TraceEventSession("MyKernelAndClrEventsSession"))
                {
                    m_EtwSession.EnableKernelProvider(KernelTraceEventParser.Keywords.NetworkTCPIP);

                    m_EtwSession.Source.Kernel.TcpIpRecv += data =>
                    {
                        if (data.ProcessID == processId)
                        {
                            lock (m_Counters)
                            {
                                m_Counters.Received += data.size;
                            }
                        }
                    };

                    m_EtwSession.Source.Kernel.TcpIpSend += data =>
                    {
                        if (data.ProcessID == processId)
                        {
                            lock (m_Counters)
                            {
                                m_Counters.Sent += data.size;
                            }
                        }
                    };

                    m_EtwSession.Source.Process();
                }
            }
            catch
            {
                ResetCounters(); // Stop reporting figures
                // Probably should log the exception
            }
        }

        public NetworkPerformanceData GetNetworkPerformanceData()
        {
            var timeDifferenceInSeconds = (DateTime.Now - m_EtwStartTime).TotalSeconds;

            NetworkPerformanceData networkData;

            lock (m_Counters)
            {
                networkData = new NetworkPerformanceData
                {
                    BytesReceived = Convert.ToInt64(m_Counters.Received / timeDifferenceInSeconds),
                    BytesSent = Convert.ToInt64(m_Counters.Sent / timeDifferenceInSeconds)
                };

            }

            // Reset the counters to get a fresh reading for next time this is called.
            ResetCounters();

            return networkData;
        }

        private void ResetCounters()
        {
            lock (m_Counters)
            {
                m_Counters.Sent = 0;
                m_Counters.Received = 0;
            }
            m_EtwStartTime = DateTime.Now;
        }

        public void Dispose()
        {
            m_EtwSession?.Dispose();
        }
    }

    public sealed class NetworkPerformanceData
    {
        public long BytesReceived { get; set; }
        public long BytesSent { get; set; }
    }
}

Solution 2

You can use PerformanceCounter. Sample code:

//Define 
string pn = "MyProcessName.exe";
var readOpSec  = new PerformanceCounter("Process","IO Read Operations/sec", pn);
var writeOpSec = new PerformanceCounter("Process","IO Write Operations/sec", pn);
var dataOpSec  = new PerformanceCounter("Process","IO Data Operations/sec", pn);
var readBytesSec = new PerformanceCounter("Process","IO Read Bytes/sec", pn);
var writeByteSec = new PerformanceCounter("Process","IO Write Bytes/sec", pn);
var dataBytesSec = new PerformanceCounter("Process","IO Data Bytes/sec", pn);

var counters = new List<PerformanceCounter>
                {
                readOpSec,
                writeOpSec,
                dataOpSec,
                readBytesSec,
                writeByteSec,
                dataBytesSec
                };

// get current value
foreach (PerformanceCounter counter in counters)
{
    float rawValue = counter.NextValue();

    // display the value
}

And this is to get performance counters for the Network card. Note it is not process specific

string cn = "get connection string from WMI";

var networkBytesSent = new PerformanceCounter("Network Interface", "Bytes Sent/sec", cn);
var networkBytesReceived = new PerformanceCounter("Network Interface", "Bytes Received/sec", cn);
var networkBytesTotal = new PerformanceCounter("Network Interface", "Bytes Total/sec", cn);

Counters.Add(networkBytesSent);
Counters.Add(networkBytesReceived);
Counters.Add(networkBytesTotal);
Share:
23,240

Related videos on Youtube

Tomer Peled
Author by

Tomer Peled

_

Updated on June 18, 2020

Comments

  • Tomer Peled
    Tomer Peled almost 4 years

    How can I get a process send/receive bytes? the preferred way is doing it with C#.

    I've searched this a lot and I didn't find any simple solution for this. Some solutions suggested to install the WinPCap on the machine and to work with this lib.

    Like this guy asked: Need "Processes with Network Activity" functionality in managed code - Like resmon.exe does it I don't want the overhead of the lib.

    Is there a simple solution for this? Actually I want the exactly data that the Resource Monitor of Windows gives under the "Processes with Network Activity" tab:enter image description here

    How does the Resource Monitor of Windows gets this information? Any example?

    Also, tried to use the counter method which is mentioned over here: Missing network sent/received but with no success - as not every process is shown under this counter. And again I'm wondering how the Resource Monitor gets this information even without using this counter...

    • Yogee
      Yogee almost 11 years
      Did not you find you answer in Performance Counter? codeproject.com/Articles/8590/…
    • Tomer Peled
      Tomer Peled almost 11 years
      I Tried to work with the Performance counters way but with no success - even read the link you added.
    • Marcello Romani
      Marcello Romani almost 11 years
    • Tomer Peled
      Tomer Peled almost 11 years
      Read it already - I don't want to use any 3rd party solution. No other native way?
  • Tomer Peled
    Tomer Peled almost 11 years
    But I want only the network activity without the device I/o operations. "IO Read Operations/sec - Shows the rate, in incidents per second, at which the process was issuing read I/O operations. It counts all I/O activity generated by the process including file, network, and device I/Os."
  • oleksii
    oleksii almost 11 years
    There is no other native way (unless you resort to 3-rd party libs) to do pure network card IO related to a single process. What I have done was monitoring process IO and also a network card IO. The later though is not specific to a process - ie it collects all IO counters irrespectively of a process. I will edit the code to show network card counters.
  • Tomer Peled
    Tomer Peled almost 11 years
    Thanks for your solution, but that is one of the solutions which I've already found and it not fulfill my goal - which is to get process network usage only. I'm looking for some other way, like the Resource Monitor of Windows gets this information...
  • user854301
    user854301 over 10 years
    Can't you just compare the process usage against the system usage? Presumably you can get interface information to decide what the maximum bandwidth is (10/100/etc.). At least I think this is probably how I'll work with it.
  • Eitan
    Eitan about 8 years
    I have asked a simmiliar question (almost - stackoverflow thought it was the same and block me by mistake, but still I don't know why the result is zero, and didn't find any clue in internet) stackoverflow.com/questions/35460656/… but I have a problem not solved yet that the result I get is always zero. Have you encountered same problem as mine that result is zero? Need some guidelines solving problem (I have also changed app.config for security decleration as link on the post ... no solution yet).
  • dean.huczok
    dean.huczok almost 7 years
    note "get connection string from WMI" can give you a different Network Interface Name (or, "description") than what PerformanceCounter uses to grab the data. On my machine, my WiFi NIC interface name from NetworkInterface.GetAllNetworkInterfaces() is "Intel(R) Centrino(R) Ultimate-N..." whereas my WiFi NIC interface name from PerformanceCounterCategory("Network Interface").GetInstanceNames() is "Intel[R] Centrino[R] Ultimate-N...", strange how one uses parentheses and the other uses brackets... :/
  • David Ferenczy Rogožan
    David Ferenczy Rogožan almost 7 years
    Does it have to be executed elevated under the administrator? I'm getting the exception System.UnauthorizedAccessException from the EnableKernelProvider method.
  • Aniket Bhansali
    Aniket Bhansali about 5 years
    Can we somehow get results while not running with admin rights? details of only current user processes would work.