获取进程发送的网络活动的接收和发送字节

537*_*037 6 .net c# process performancecounter

这是我上一个问题的下一步。


我正在创建一个C#WinForm应用程序,它将显示给定进程(例如:进程名的chrome.exe)的网络活动(接收的字节数/发送的字节数)和该进程生成的兆位/秒的速度。

在使用性能计数器IO Read Bytes/secIO Read Bytes/sec显示I / O读写字节而不是“发送和接收字节”时

PS:I / O计算由进程生成的所有文件,网络和设备I / O字节。但是,我只希望由特定进程生成的网络字节。

我只想检索接收的字节数和发送的字节数。但是,不知道使用什么计数器来获取进程的这些字节。

我已经为此目的搜索了这些链接,但没有用:

这是尝试过的Process的Performance Counter代码:

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;
Run Code Online (Sandbox Code Playgroud)

问题:如何仅获取由进程为网络活动生成的已接收和已发送字节。

Jan*_*ann 5

正如评论中已经提到的,我认为没有办法使用PerformanceCounter该类来实现这一点。由于它使用 Windows 的内置性能计数器,因此可以通过使用该typeperf命令查询已安装计数器的整个列表来验证这一点。在我的本地机器上,这会产生大约 3.200 个不同的计数器,我通过这些计数器来验证我的声明。实际上用于网络发送/接收的计数器(甚至对于特定的网络接口/适配器或处理器),但它们都不能过滤特定的进程或进程系列。


因此,更简单的方法可能是使用这个(已经非常完整)的答案,它利用了Microsoft.Diagnostics.Tracing.TraceEventNuGet 包。为了测试,我将其压缩为最少量的代码并对其进行修改以捕获整个进程系列的流量。

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");
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,您需要提升(管理员)权限才能执行此代码。

我用 Mozilla Firefox 进行了测试,当时它有 10 个进程(7 个选项卡)在运行;我下载了一个大文件,程序正确打印了添加的网络流量(加上活动选项卡的一些噪音),而不包括涉及的磁盘访问(这至少会使测量的流量增加一倍)。

另请注意,这仅捕获 TCP/IP 流量;要同时捕获 UDP/IP 流量,您需要订阅UdpIpSendUdpIpRecv事件。