如何通过Cmd/PowerShell获取特定应用的每秒网络收发字节数
获取特定应用的网络收发字节数
问题分析
你尝试的Microsoft-Windows-Kernel-Network是内核态提供者,仅记录内核层面的网络操作,关联的PID多为系统进程,无法直接映射到用户态应用。要获取应用级的网络收发数据,需要使用用户态网络API相关的ETW提供者,或结合进程端口关联的方式。
方案1:使用Microsoft-Windows-Winsock-Api ETW提供者
这个提供者记录用户态应用调用Winsock API的网络操作(如send/recv),能直接关联到应用的PID,可提取收发字节数。
PowerShell脚本示例
# 定义日志路径 $logPath = "C:\temp\WinsockTrace.etl" # 创建ETW跟踪会话,指定Winsock API提供者 logman create trace "WinsockAppTrace" -p "Microsoft-Windows-Winsock-Api" -o $logPath -ets # 运行跟踪一段时间(这里暂停10秒,可根据需求调整) Start-Sleep -Seconds 10 # 停止跟踪会话 logman stop "WinsockAppTrace" -ets # 解析日志,过滤发送/接收操作并关联进程信息 Get-WinEvent -Path $logPath -Oldest | Where-Object { $_.Id -in 1000, 1001, 1002, 1003 # 对应send、recv等操作的事件ID } | ForEach-Object { $pid = $_.Properties[0].Value $processName = (Get-Process -Id $pid -ErrorAction SilentlyContinue).Name $bytes = $_.Properties[2].Value # 收发字节数字段 $operation = switch ($_.Id) { 1000 { "Send" } 1001 { "SendTo" } 1002 { "Recv" } 1003 { "RecvFrom" } } [PSCustomObject]@{ ProcessName = $processName PID = $pid Operation = $operation Bytes = $bytes Timestamp = $_.TimeCreated } } | Format-Table -AutoSize
方案2:结合端口关联与性能计数器
如果ETW跟踪过于复杂,可通过以下步骤间接获取:
- 用
netstat -ano或PowerShell的Get-NetTCPConnection获取目标应用的PID和关联端口。 - 读取性能计数器中对应端口的收发字节数:
# 获取目标进程的PID(替换为你的应用PID) $targetPid = 1234 # 获取进程关联的TCP端口 $ports = Get-NetTCPConnection -OwningProcess $targetPid | Select-Object -ExpandProperty LocalPort # 读取每个端口的TCP收发字节数 foreach ($port in $ports) { $counterSent = Get-Counter "\TCPv4\Connections Established($port)\Bytes Sent/sec" -ErrorAction SilentlyContinue $counterReceived = Get-Counter "\TCPv4\Connections Established($port)\Bytes Received/sec" -ErrorAction SilentlyContinue [PSCustomObject]@{ ProcessName = (Get-Process -Id $targetPid).Name Port = $port BytesSentPerSec = $counterSent.CounterSamples.CookedValue BytesReceivedPerSec = $counterReceived.CounterSamples.CookedValue } }
方案3:使用Microsoft-Windows-TCPIP提供者
该提供者记录TCP/IP层的详细操作,也能关联到用户态进程PID,适合更底层的流量统计:
$logPath = "C:\temp\TCPIPTrace.etl" logman create trace "TCPIPAppTrace" -p "Microsoft-Windows-TCPIP" -o $logPath -ets Start-Sleep -Seconds 10 logman stop "TCPIPAppTrace" -ets Get-WinEvent -Path $logPath -Oldest | Where-Object { $_.OpcodeDisplayName -in "Send", "Receive" } | ForEach-Object { $pid = $_.Properties[1].Value [PSCustomObject]@{ ProcessName = (Get-Process -Id $pid -ErrorAction SilentlyContinue).Name PID = $pid Operation = $_.OpcodeDisplayName Bytes = $_.Properties[3].Value Timestamp = $_.TimeCreated } } | Format-Table -AutoSize
内容的提问来源于stack exchange,提问作者Vedang Agarwal
相关产品推荐
相关产品推荐

