24

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...

Community
  • 1
  • 1
Tomer Peled
  • 3,472
  • 4
  • 30
  • 51

3 Answers3

15

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; }
    }
}
Kram
  • 3,722
  • 4
  • 36
  • 57
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);
oleksii
  • 33,544
  • 11
  • 83
  • 149
  • 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." – Tomer Peled Jun 10 '13 at 14:39
  • 1
    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. – oleksii Jun 10 '13 at 14:45
  • 1
    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... – Tomer Peled Jun 11 '13 at 05:53
  • 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. – TheXenocide Oct 03 '13 at 20:38
  • 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) http://stackoverflow.com/questions/35460656/c-sharp-check-connectivity-to-endpoint?noredirect=1#comment58645231_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). – Eitan Feb 20 '16 at 11:06
  • 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... :/ – dean.huczok Jul 17 '17 at 06:21
0

Have a look at the IP Helper API. There is an implementation in C# by Simon Mourier that sums transferred bytes per process: https://stackoverflow.com/a/25650933/385513

It would be interesting to know how this compares with Event Tracing for Windows (ETW)...

st12
  • 2,655
  • 4
  • 23
  • 38