Retrieving top x process consuming most CPU, Memory, Disk and Network

Darren Rose 306 Reputation points
2025-03-14T10:31:28.26+00:00

Hi

I need to obtain top x processes using the most CPU, Memory, Disk and Network.

CPU I have working using Performance Counters and % Processor Time

Memory I have working using Process.GetProcesses and looking at either PrivateMemorySize64 or WorkingSet64 - not yet sure best one to use

But I am struggling for Disk or Network as lots of solutions use Win32_PerfRawData_PerfProc_Process but values here cover both network and disk combined not separately

Thanks

VB
VB
An object-oriented programming language developed by Microsoft that is implemented on the .NET Framework. Previously known as Visual Basic .NET.
2,823 questions
0 comments No comments
{count} votes

Accepted answer
  1. Castorix31 88,376 Reputation points
    2025-03-17T13:00:51.6+00:00

    As TCPView calls

    GetExtendedUdpTable and GetExtendedTcpTable

    but also

    OpenTrace, StartTrace, ... with "NT Kernel Logger", it can be complicated to do the same thing in VB.NET, then to simplify, I did this test with the help of ChatGPT and Microsoft.Diagnostics.Tracing.TraceEvent Nuget Package

    You can ask ChatGPT (or Copilot) to change aggregation (PID instead of PID + Protocol) and do the same thing for disk

    (KernelTraceEventParser.Keywords.DiskIO or KernelTraceEventParser.Keywords.FileIO)

    Imports Microsoft.Diagnostics.Tracing.Parsers
    Imports Microsoft.Diagnostics.Tracing.Session
    Imports System.Collections.Concurrent
    Imports System.Diagnostics
    
    Public Class Form1
    
        Public Class TrafficStat
            Public Property Sent As Long
            Public Property Received As Long
        End Class
    
        Private Shared ProcessTraffic As New ConcurrentDictionary(Of Tuple(Of Integer, String), TrafficStat)()
        Private Shared traceSession As TraceEventSession
    
        Private grid As DataGridView
        Private refreshTimer As System.Windows.Forms.Timer
    
        Public Sub New()
            InitializeComponent()
        End Sub
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            ' Add Manifest file with requireAdministrator
            If Not IsAdministrator() Then
                MessageBox.Show("Please run this app as Administrator!", "Admin Rights Needed", MessageBoxButtons.OK, MessageBoxIcon.Warning)
                Return
            End If
    
            Text = "TCP/UDP Process Monitor"
            Width = 800
            Height = 600
    
            grid = New DataGridView() With {
                .Dock = DockStyle.Fill,
                .ReadOnly = True,
                .AutoGenerateColumns = False,
                .AllowUserToAddRows = False
            }
    
            grid.Columns.Add(New DataGridViewTextBoxColumn() With {.HeaderText = "PID", .DataPropertyName = "PID"})
            grid.Columns.Add(New DataGridViewTextBoxColumn() With {.HeaderText = "Process", .DataPropertyName = "ProcessName", .Width = 200})
            grid.Columns.Add(New DataGridViewTextBoxColumn() With {.HeaderText = "Protocol", .DataPropertyName = "Protocol"})
            grid.Columns.Add(New DataGridViewTextBoxColumn() With {.HeaderText = "Sent Bytes", .DataPropertyName = "SentBytes"})
            grid.Columns.Add(New DataGridViewTextBoxColumn() With {.HeaderText = "Received Bytes", .DataPropertyName = "ReceivedBytes"})
            grid.Columns.Add(New DataGridViewTextBoxColumn() With {.HeaderText = "Total Bytes", .DataPropertyName = "TotalBytes"})
    
            Controls.Add(grid)
    
            StartETWListener()
    
            refreshTimer = New System.Windows.Forms.Timer() With {.Interval = 2000}
            AddHandler refreshTimer.Tick, AddressOf RefreshProcessList
            refreshTimer.Start()
        End Sub
    
        Private Shared Sub StartETWListener()
            traceSession = New TraceEventSession("MyKernelNetworkSession")
    
            ' Enable Network TCPIP events (covers both v4 and v6 when you subscribe correctly)
            traceSession.EnableKernelProvider(KernelTraceEventParser.Keywords.NetworkTCPIP)
    
            Task.Run(Sub()
                         Dim kernel = traceSession.Source.Kernel
    
                         ' TCP IPv4
                         AddHandler kernel.TcpIpRecv, Sub(data)
                                                          Dim pid = data.ProcessID
                                                          Dim size = data.size
                                                          Dim protocol = "TCP"
    
                                                          Dim key = Tuple.Create(pid, protocol)
                                                          ProcessTraffic.AddOrUpdate(key, New TrafficStat With {.Sent = 0, .Received = size},
                                                                                      Function(k, oldStat)
                                                                                          oldStat.Received += size
                                                                                          Return oldStat
                                                                                      End Function)
                                                      End Sub
    
                         AddHandler kernel.TcpIpSend, Sub(data)
                                                          Dim pid = data.ProcessID
                                                          Dim size = data.size
                                                          Dim protocol = "TCP"
    
                                                          Dim key = Tuple.Create(pid, protocol)
                                                          ProcessTraffic.AddOrUpdate(key, New TrafficStat With {.Sent = size, .Received = 0},
                                                                                      Function(k, oldStat)
                                                                                          oldStat.Sent += size
                                                                                          Return oldStat
                                                                                      End Function)
                                                      End Sub
    
                         ' TCP IPv6
                         AddHandler kernel.TcpIpRecvIPV6, Sub(data)
                                                              Dim pid = data.ProcessID
                                                              Dim size = data.size
                                                              Dim protocol = "TCPv6"
    
                                                              Dim key = Tuple.Create(pid, protocol)
                                                              ProcessTraffic.AddOrUpdate(key, New TrafficStat With {.Sent = 0, .Received = size},
                                                                                          Function(k, oldStat)
                                                                                              oldStat.Received += size
                                                                                              Return oldStat
                                                                                          End Function)
                                                          End Sub
    
                         AddHandler kernel.TcpIpSendIPV6, Sub(data)
                                                              Dim pid = data.ProcessID
                                                              Dim size = data.size
                                                              Dim protocol = "TCPv6"
    
                                                              Dim key = Tuple.Create(pid, protocol)
                                                              ProcessTraffic.AddOrUpdate(key, New TrafficStat With {.Sent = size, .Received = 0},
                                                                                          Function(k, oldStat)
                                                                                              oldStat.Sent += size
                                                                                              Return oldStat
                                                                                          End Function)
                                                          End Sub
    
                         ' UDP IPv4
                         AddHandler kernel.UdpIpRecv, Sub(data)
                                                          Dim pid = data.ProcessID
                                                          Dim size = data.size
                                                          Dim protocol = "UDP"
    
                                                          Dim key = Tuple.Create(pid, protocol)
                                                          ProcessTraffic.AddOrUpdate(key, New TrafficStat With {.Sent = 0, .Received = size},
                                                                                     Function(k, oldStat)
                                                                                         oldStat.Received += size
                                                                                         Return oldStat
                                                                                     End Function)
                                                      End Sub
    
                         AddHandler kernel.UdpIpSend, Sub(data)
                                                          Dim pid = data.ProcessID
                                                          Dim size = data.size
                                                          Dim protocol = "UDP"
    
                                                          Dim key = Tuple.Create(pid, protocol)
                                                          ProcessTraffic.AddOrUpdate(key, New TrafficStat With {.Sent = size, .Received = 0},
                                                                                     Function(k, oldStat)
                                                                                         oldStat.Sent += size
                                                                                         Return oldStat
                                                                                     End Function)
                                                      End Sub
    
                         ' UDP IPv6
                         AddHandler kernel.UdpIpRecvIPV6, Sub(data)
                                                              Dim pid = data.ProcessID
                                                              Dim size = data.size
                                                              Dim protocol = "UDPv6"
    
                                                              Dim key = Tuple.Create(pid, protocol)
                                                              ProcessTraffic.AddOrUpdate(key, New TrafficStat With {.Sent = 0, .Received = size},
                                                                                          Function(k, oldStat)
                                                                                              oldStat.Received += size
                                                                                              Return oldStat
                                                                                          End Function)
                                                          End Sub
    
                         AddHandler kernel.UdpIpSendIPV6, Sub(data)
                                                              Dim pid = data.ProcessID
                                                              Dim size = data.size
                                                              Dim protocol = "UDPv6"
    
                                                              Dim key = Tuple.Create(pid, protocol)
                                                              ProcessTraffic.AddOrUpdate(key, New TrafficStat With {.Sent = size, .Received = 0},
                                                                                          Function(k, oldStat)
                                                                                              oldStat.Sent += size
                                                                                              Return oldStat
                                                                                          End Function)
                                                          End Sub
    
                         traceSession.Source.Process()
                     End Sub)
        End Sub
    
        Private Shared Function IsAdministrator() As Boolean
            Dim identity = System.Security.Principal.WindowsIdentity.GetCurrent()
            Dim principal = New System.Security.Principal.WindowsPrincipal(identity)
            Return principal.IsInRole(System.Security.Principal.WindowsBuiltInRole.Administrator)
        End Function
    
    
        Private Sub RefreshProcessList()
            Dim processes = Process.GetProcesses().ToDictionary(Function(p) p.Id, Function(p) p.ProcessName)
    
            Dim stats = ProcessTraffic.
                Select(Function(kvp)
                           Dim key = kvp.Key ' Tuple(Of Integer, String)
                           Dim pid = key.Item1
                           Dim protocol = key.Item2
    
                           Dim stat = kvp.Value
    
                           Dim processName As String = Nothing
                           processes.TryGetValue(pid, processName)
    
                           Return New ProcessStat With {
                               .PID = pid,
                               .ProcessName = If(processName, "Unknown"),
                               .Protocol = protocol,
                               .SentBytes = stat.Sent,
                               .ReceivedBytes = stat.Received,
                               .TotalBytes = stat.Sent + stat.Received
                           }
                       End Function).
                OrderByDescending(Function(p) p.TotalBytes).
                ToList()
    
            grid.DataSource = stats
        End Sub
    
        Private Class ProcessStat
            Public Property PID As Integer
            Public Property ProcessName As String
            Public Property Protocol As String
            Public Property SentBytes As Long
            Public Property ReceivedBytes As Long
            Public Property TotalBytes As Long
        End Class
    
    End Class
    
    
    1 person found this answer helpful.

1 additional answer

Sort by: Most helpful
  1. Jiachen Li-MSFT 34,206 Reputation points Microsoft External Staff
    2025-03-14T13:15:54.2433333+00:00

    Hi @Darren Rose ,

    You can use performance counters like IO Read Bytes/sec and IO Write Bytes/sec to track per-process disk activity.

    
        Dim diskCounter As New PerformanceCounter("Process", "IO Data Bytes/sec", "_Total")
        Dim networkCounter As New PerformanceCounter("Process", "IO Other Bytes/sec", "_Total")
    
        Console.WriteLine("Disk I/O: " & diskCounter.NextValue() & " bytes/sec")
        Console.WriteLine("Network I/O: " & networkCounter.NextValue() & " bytes/sec
    
    

    Best Regards.

    Jiachen Li


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment". Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.