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:
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With