【问题标题】:Retrieve process network usage检索进程网络使用情况
【发布时间】:2013-06-06 05:54:08
【问题描述】:

如何获取进程发送/接收字节?首选方法是使用 C#。

我对此进行了很多搜索,但没有找到任何简单的解决方案。一些解决方案建议在机器上安装 WinPCap 并使用此库。

就像这个人问的:Need "Processes with Network Activity" functionality in managed code - Like resmon.exe does it 我不想要库的开销。

有没有简单的解决方案? 实际上,我想要 Windows 的资源监视器在“具有网络活动的进程”选项卡下提供的确切数据:

Windows 的资源监视器如何获取此信息? 有什么例子吗?

另外,尝试使用此处提到的计数器方法: Missing network sent/received 但没有成功 - 因为并非每个进程都显示在此计数器下。 我再次想知道即使不使用此计数器,资源监视器如何获取此信息...

【问题讨论】:

标签: c# .net networking network-programming performancecounter


【解决方案1】:

资源监视器使用ETW - 值得庆幸的是,微软创建了一个很好的nuget .net wrapper 以使其更易于使用。

我最近写了这样的东西来报告我的进程的网络 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; }
    }
}

【讨论】:

  • 是否必须在管理员权限下执行?我从EnableKernelProvider 方法中得到了异常System.UnauthorizedAccessException
  • 我们可以在没有管理员权限的情况下以某种方式获得结果吗?只有当前用户进程的详细信息才有效。
【解决方案2】:

您可以使用PerformanceCounter。示例代码:

//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
}

这是为了获取网卡的性能计数器。请注意,它不是特定于进程的

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);

【讨论】:

  • 但我只想要没有设备 I/O 操作的网络活动。 “IO 读取操作/秒 - 显示进程发出读取 I/O 操作的速率(以每秒事件数为单位)。它计算进程生成的所有 I/O 活动,包括文件、网络和设备 I/O。 "
  • 没有其他本地方式(除非您使用 3-rd 方库)来执行与单个进程相关的纯网卡 IO。我所做的是监控进程 IO 和网卡 IO。后者虽然不是特定于某个进程 - 即它收集所有 IO 计数器,而与进程无关。我将编辑代码以显示网卡计数器。
  • 感谢您的解决方案,但这是我已经找到的解决方案之一,它不能实现我的目标 - 即仅获得进程网络使用。我正在寻找其他方式,例如 Windows 的资源监视器获取此信息...
  • 您不能只比较进程使用情况和系统使用情况吗?大概你可以获取接口信息来决定最大带宽是多少(10/100/等)。至少我认为这可能是我的工作方式。
  • 我问了一个类似的问题(几乎 - stackoverflow 认为它是相同的并且错误地阻止了我,但我仍然不知道为什么结果为零,并且没有找到任何线索互联网)stackoverflow.com/questions/35460656/… 但我有一个问题尚未解决,我得到的结果始终为零。你有没有遇到和我一样的问题,结果是零?需要一些指导方针来解决问题(我还更改了 app.config 以进行安全声明作为帖子上的链接......目前还没有解决方案)。
【解决方案3】:

看看IP Helper APISimon Mourier 在 C# 中实现了每个进程传输的字节数:https://stackoverflow.com/a/25650933/385513

知道这与Event Tracing for Windows (ETW) 相比如何会很有趣...

【讨论】:

    猜你喜欢
    • 2010-10-01
    • 2015-12-29
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-25
    • 2020-12-06
    相关资源
    最近更新 更多