Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting Received and Sent Bytes generated by Process for Network Activity

This is next step of my previous question.


I'm creating a C# WinForm Application which will display Network Activity (Bytes Received / Bytes Sent) for a given Process (For Example: Process name 's chrome.exe) and Speed in Megabits/s generated by the Process.

While using the Performance Counters IO Read Bytes/sec and IO Read Bytes/sec shows I/O read and write bytes instead of 'Send and Received Bytes'.

PS: I/O counts all File, Network, and Device I/Os bytes generated by a Process. But, I wants only Network Bytes generated by a particular Process.

I wanted to retrieve only Bytes Received and Bytes Sent. But, don't know what counters are used to get these bytes of a Process.

I have searched these links for this purpose but not useful:

  • C# Resource Monitor get network activity values
  • Retrieve process network usage
  • Missing network sent/received
  • Need "Processes with Network Activity" functionality in managed code - Like resmon.exe does it

Here is Process's Performance Counter code that tried:

PerformanceCounter bytesReceived = new PerformanceCounter("Process", "IO Read Bytes/sec");
PerformanceCounter bytesSent = new PerformanceCounter("Process", "IO Write Bytes/sec");
string ProcessName = "chrome";
bytesReceived.InstanceName = ProcessName;
bytesSent.InstanceName = ProcessName;

Question: How I can only get the Received and Sent Bytes generated by a Process for a network activity.

like image 882
youpilat13 Avatar asked Sep 17 '19 16:09

youpilat13


1 Answers

As already mentioned in the comments, I don't believe there is a way to achieve this using the PerformanceCounter class. Since it uses Windows' built-in performance counters, this can be verified by querying the entire list of installed counters using the typeperf command. On my local machine this yields about 3.200 different counters, which I went through to verify my claim. There actually are counters for network send/receive (even for specific network interfaces/adapters or processors), but none of them can filter for a specific process or process family.


Thus, the easier way might be to use this (already quite complete) answer, which makes use of the Microsoft.Diagnostics.Tracing.TraceEvent NuGet package. For testing I condensed it down to a minimal amount of code and modified it to capture the traffic of an entire process family.

static void Main(string[] args)
{
    // Counter variables
    var counterLock = new object();
    int received = 0;
    int sent = 0;

    // Fetch ID of all Firefox processes
    var processList = Process.GetProcessesByName("firefox").Select(p => p.Id).ToHashSet();

    // Run in another thread, since this will be a blocking operation (see below)
    Task.Run(() =>
    {
        // Start ETW session
        using(var session = new TraceEventSession("MyKernelAndClrEventsSession"))
        {
            // Query network events
            session.EnableKernelProvider(KernelTraceEventParser.Keywords.NetworkTCPIP);

            // Subscribe to trace events
            // These will be called by another thread, so locking is needed here
            session.Source.Kernel.TcpIpRecv += data =>
            {
                if(processList.Contains(data.ProcessID))
                    lock(counterLock)
                        received += data.size;
            };
            session.Source.Kernel.TcpIpSend += data =>
            {
                if(processList.Contains(data.ProcessID))
                    lock(counterLock)
                        sent += data.size;
            };

            // Process all events (this will block)
            session.Source.Process();
        }
    });

    // Program logic to handle counter values
    while(true)
    {
        // Wait some time and print current counter status
        Task.Delay(2000).Wait();
        lock(counterLock)
            Console.WriteLine($"Sent: {sent.ToString("N0")} bytes    Received: {received.ToString("N0")} bytes");
    }
}

Note that you need elevated (administrator) privileges to execute this code.

I tested with Mozilla Firefox, which had 10 processes (7 tabs) running at that time; I downloaded a big file, and the program correctly printed the added network traffic (plus some noise from active tabs), without including the involved disk accesses (which would have at least doubled the measured traffic).

Also note that this only captures TCP/IP traffic; to also capture UDP/IP traffic, you need to subscribe to the UdpIpSend and UdpIpRecv events.

like image 123
janw Avatar answered Sep 20 '22 17:09

janw