Windows 字节任务管理器 Received/Interval 使用了哪个函数?
Which function is used in Windows Task Manager for Bytes Received/Interval?
我写了一个应用程序,它使用 GetIfTable
函数来显示每秒收到的字节数,但它不适用于 windows7。
1- windows 任务管理器中使用了哪个函数来显示字节 Received/Interval?
2- 是否有任何库可以获取有关连接过程等信息?
3- 您知道任何开源应用程序,例如 Process Explorer 或 glint 吗?
任务管理器显示来自 Windows 性能计数器的信息。 "Network Interface" 性能计数器对象的实例通常是计算机的以太网适配器。从这些中,它可以每秒获取数据包 sent/received,每秒获取字节 sent/received——与任务管理器可以显示的内容相同。
下面的代码使用 "PDH" 接口访问性能计数器。首先,创建一个Query
对象,然后使用它的SetObject
成员函数告诉它你想使用哪个对象。此示例选择 "Network Interface" 对象,但您可以通过调用 Query::DumpAvailableObjects
.
查看所有可用对象的列表
选择对象后,它会自动选择为该对象找到的第一个实例。如果要设置不同的实例,请调用 query.DumpAvailableInstances
.
您还需要告诉 Query 要显示哪些计数器。使用 query.AddCounter
添加您从 queryDumpAvailableCounters
获得的计数器列表中的名称。该示例添加了两个计数器,"Bytes Received/sec"
和 "Bytes Sent/sec"
。但是还有很多其他的你可以试试。
调用 query.CounterPollingDump
开始显示来自计数器的数据。这是一个循环,它会一直重复,直到您按下 Ctrl-Break。
要构建示例,请创建一个新的控制台应用程序并将其复制到其源文件中。我使用 Visual Studio 2013.
#include <Windows.h>
#include <pdh.h>
#include <pdhmsg.h>
#include <iostream>
#include <ios>
#include <string>
#include <vector>
#pragma comment(lib, "Pdh.lib")
static std::string CounterPath(std::string object_name, std::string counter_name, std::string instance_name) {
PDH_COUNTER_PATH_ELEMENTS_A path_elements = {0};
path_elements.szObjectName = &object_name[0];
path_elements.szCounterName = &counter_name[0];
path_elements.szInstanceName = &instance_name[0];
std::string path(PDH_MAX_COUNTER_PATH+1, '[=10=]');
DWORD len = PDH_MAX_COUNTER_PATH;
auto status = PdhMakeCounterPathA(&path_elements, &path[0], &len, 0);
if(status != ERROR_SUCCESS) {
std::cout << std::hex << status << '\n';
return std::string("Error");
}
path.resize(len - (path[len-1] == '[=10=]'));
return path;
}
using namelist_t = std::vector<std::string>;
// no arguments overload gives an empty name list
static namelist_t NameListParser() { return namelist_t(); }
static namelist_t NameListParser(const std::string& buffer) {
namelist_t names;
auto iter = buffer.begin();
do {
std::string name;
while(iter != buffer.end() && *iter) {
name += *(iter++);
}
if(!name.empty()) {
names.push_back(name);
}
} while(iter != buffer.end() && ++iter != buffer.end() && *iter);
return names;
}
template <typename T>
static void DumpList(const T& list, const char* item_separator=nullptr, const char* item_prefix=nullptr, const char* list_prefix=nullptr, const char* list_postfix=nullptr) {
if(!item_separator) item_separator = "\n";
if(!item_prefix) item_prefix = " ";
if(!list_prefix) list_prefix = "";
if(!list_postfix) list_postfix = "\n";
std::cout << list_prefix;
bool first = true;
for(const auto& elem : list) {
if(first) { first = false; }
else { std::cout << item_separator; }
std::cout << item_prefix << elem;
}
std::cout << list_postfix;
}
static namelist_t ListObjectNames() {
DWORD buflen = 0;
const DWORD detail_level = PERF_DETAIL_WIZARD;
PdhEnumObjectsA(0, 0, 0, &buflen, detail_level, TRUE);
std::string namebuf(buflen, '[=10=]');
auto status = PdhEnumObjectsA(0, 0, &namebuf[0], &buflen, detail_level, FALSE);
if(status != ERROR_SUCCESS) {
return NameListParser();
}
return NameListParser(namebuf);
}
struct CounterNames { namelist_t counters, instances; };
static CounterNames ListCounters(const std::string& object_name) {
DWORD counter_list_size = 0;
DWORD instance_list_size = 0;
const DWORD detail_level = PERF_DETAIL_WIZARD;
PdhEnumObjectItemsA(0, 0, object_name.c_str(), 0, &counter_list_size, 0, &instance_list_size, detail_level, 0);
std::string counter_buf(counter_list_size, '[=10=]');
std::string inst_buf(instance_list_size, '[=10=]');
auto status = PdhEnumObjectItemsA(0, 0, object_name.c_str(), &counter_buf[0], &counter_list_size, &inst_buf[0], &instance_list_size, detail_level, 0);
if(status != ERROR_SUCCESS) {
return CounterNames();
}
auto counters = NameListParser(counter_buf);
auto instances = NameListParser(inst_buf);
return { counters, instances };
}
class Query {
struct CounterData {
PDH_HCOUNTER hcounter;
std::string name;
std::string path;
};
PDH_HQUERY hquery;
std::vector<CounterData> counter_list;
std::string object_name;
std::string instance_name;
volatile bool keep_going;
public:
Query() {
PdhOpenQuery(0, 0, &hquery) == ERROR_SUCCESS || (hquery = 0);
}
Query(const Query&) = delete;
Query(Query&& src) : hquery(src.hquery) {
src.hquery = 0;
// std::move these if you want
// this is really just for keeping hquery unique
counter_list = src.counter_list;
object_name = src.object_name;
instance_name = src.instance_name;
}
Query& operator = (const Query&) = delete;
Query& operator = (Query&& src) {
if(hquery) PdhCloseQuery(hquery);
hquery = src.hquery;
src.hquery = 0;
counter_list = src.counter_list;
object_name = src.object_name;
instance_name = src.instance_name;
return *this;
}
~Query() {
if(!hquery) return;
PdhCloseQuery(hquery);
// Counter handles belong to the query and
// don't appear to need separate closing by
// the user.
}
operator PDH_HQUERY () const { return hquery; }
bool IsOk() const { return !!hquery; }
operator const void* () const { return (const void*)IsOk(); }
void SetInstance(const std::string& name) { instance_name = name; }
void SetObject(const std::string& name) {
object_name = name;
auto counter_names = ListCounters(name);
if(counter_names.instances.size()) {
std::cout << "Automatically selecting instance \"" << counter_names.instances[0] << "\"\n";
SetInstance(counter_names.instances[0]);
}
}
static void DumpAvailableObjects() {
DumpList(ListObjectNames());
}
void DumpAvailableCounters() const {
if(object_name.empty()) {
std::cout << "DumpAvailableCounters: An object needs to be set before calling\n";
return;
}
auto counter_names = ListCounters(object_name);
DumpList(counter_names.counters);
}
void DumpAvailableInstances() const {
if(object_name.empty()) {
std::cout << "DumpAvailableInstances: An object needs to be set before calling\n";
return;
}
auto counter_names = ListCounters(object_name);
DumpList(counter_names.instances);
}
void AddCounter() {}
template <typename ...more>
void AddCounter(const std::string& name, more... args) {
if(!hquery) {
std::cout << "AddCounter: Query was not successfully created\n";
return;
}
if(object_name.empty()) {
std::cout << "AddCounter: No Object Name selected\n";
return;
}
if(instance_name.empty()) {
std::cout << "AddCounter: No Instance Name selected\n";
return;
}
CounterData counter_data;
counter_data.name = name;
counter_data.path = CounterPath(object_name, name, instance_name);
auto status = PdhAddCounterA(hquery, counter_data.path.c_str(), 0, &counter_data.hcounter);
if(status != ERROR_SUCCESS) {
std::cout << "AddCounter Failed: " << std::hex << status << '\n';
return;
}
counter_list.push_back(counter_data);
AddCounter(args...);
}
void CounterPollingDump(DWORD polling_interval_ms = 1000) {
if(counter_list.empty()) {
std::cout << "CounterPollingDump: Nothing to do, the Counter List is empty\n";
return;
}
size_t max_name_len = 0;
for(const auto& counter : counter_list) {
if(counter.name.length() > max_name_len) max_name_len = counter.name.length();
}
keep_going = true;
do {
Sleep(polling_interval_ms);
auto status = PdhCollectQueryData(hquery);
if(status != ERROR_SUCCESS) {
std::cout << "CounterPollingDump: PdhCollectQueryData failed: " << std::hex << status << '\n';
return;
}
std::cout << " =======================\n";
for(const auto& counter : counter_list) {
const std::string spaces(max_name_len-counter.name.length()+2, ' ');
std::cout << counter.name << spaces;
DWORD counter_type;
PDH_FMT_COUNTERVALUE fmt_value = {0};
auto status = PdhGetFormattedCounterValue(counter.hcounter, PDH_FMT_DOUBLE, &counter_type, &fmt_value);
if(status != ERROR_SUCCESS) {
if(status == PDH_INVALID_DATA) {
std::cout << " -- no data --\n";
continue;
}
std::cout << "CounterPollingDump: PdhGetFormattedCounterValue failed: " << std::hex << status << '\n';
return;
}
std::cout << " " << fmt_value.doubleValue << '\n';
}
} while(keep_going);
}
void StopPolling() {
keep_going = false;
}
};
int main() {
Query query;
//query.DumpAvailableObjects();
query.SetObject("Network Interface");
//query.DumpAvailableCounters();
//query.DumpAvailableInstances();
//query.SetInstance("Some Other Ethernet Device");
query.AddCounter("Bytes Received/sec");
query.AddCounter("Bytes Sent/sec");
query.CounterPollingDump(); // loops until you Ctrl-Break
}
我写了一个应用程序,它使用 GetIfTable
函数来显示每秒收到的字节数,但它不适用于 windows7。
1- windows 任务管理器中使用了哪个函数来显示字节 Received/Interval?
2- 是否有任何库可以获取有关连接过程等信息?
3- 您知道任何开源应用程序,例如 Process Explorer 或 glint 吗?
任务管理器显示来自 Windows 性能计数器的信息。 "Network Interface" 性能计数器对象的实例通常是计算机的以太网适配器。从这些中,它可以每秒获取数据包 sent/received,每秒获取字节 sent/received——与任务管理器可以显示的内容相同。
下面的代码使用 "PDH" 接口访问性能计数器。首先,创建一个Query
对象,然后使用它的SetObject
成员函数告诉它你想使用哪个对象。此示例选择 "Network Interface" 对象,但您可以通过调用 Query::DumpAvailableObjects
.
选择对象后,它会自动选择为该对象找到的第一个实例。如果要设置不同的实例,请调用 query.DumpAvailableInstances
.
您还需要告诉 Query 要显示哪些计数器。使用 query.AddCounter
添加您从 queryDumpAvailableCounters
获得的计数器列表中的名称。该示例添加了两个计数器,"Bytes Received/sec"
和 "Bytes Sent/sec"
。但是还有很多其他的你可以试试。
调用 query.CounterPollingDump
开始显示来自计数器的数据。这是一个循环,它会一直重复,直到您按下 Ctrl-Break。
要构建示例,请创建一个新的控制台应用程序并将其复制到其源文件中。我使用 Visual Studio 2013.
#include <Windows.h>
#include <pdh.h>
#include <pdhmsg.h>
#include <iostream>
#include <ios>
#include <string>
#include <vector>
#pragma comment(lib, "Pdh.lib")
static std::string CounterPath(std::string object_name, std::string counter_name, std::string instance_name) {
PDH_COUNTER_PATH_ELEMENTS_A path_elements = {0};
path_elements.szObjectName = &object_name[0];
path_elements.szCounterName = &counter_name[0];
path_elements.szInstanceName = &instance_name[0];
std::string path(PDH_MAX_COUNTER_PATH+1, '[=10=]');
DWORD len = PDH_MAX_COUNTER_PATH;
auto status = PdhMakeCounterPathA(&path_elements, &path[0], &len, 0);
if(status != ERROR_SUCCESS) {
std::cout << std::hex << status << '\n';
return std::string("Error");
}
path.resize(len - (path[len-1] == '[=10=]'));
return path;
}
using namelist_t = std::vector<std::string>;
// no arguments overload gives an empty name list
static namelist_t NameListParser() { return namelist_t(); }
static namelist_t NameListParser(const std::string& buffer) {
namelist_t names;
auto iter = buffer.begin();
do {
std::string name;
while(iter != buffer.end() && *iter) {
name += *(iter++);
}
if(!name.empty()) {
names.push_back(name);
}
} while(iter != buffer.end() && ++iter != buffer.end() && *iter);
return names;
}
template <typename T>
static void DumpList(const T& list, const char* item_separator=nullptr, const char* item_prefix=nullptr, const char* list_prefix=nullptr, const char* list_postfix=nullptr) {
if(!item_separator) item_separator = "\n";
if(!item_prefix) item_prefix = " ";
if(!list_prefix) list_prefix = "";
if(!list_postfix) list_postfix = "\n";
std::cout << list_prefix;
bool first = true;
for(const auto& elem : list) {
if(first) { first = false; }
else { std::cout << item_separator; }
std::cout << item_prefix << elem;
}
std::cout << list_postfix;
}
static namelist_t ListObjectNames() {
DWORD buflen = 0;
const DWORD detail_level = PERF_DETAIL_WIZARD;
PdhEnumObjectsA(0, 0, 0, &buflen, detail_level, TRUE);
std::string namebuf(buflen, '[=10=]');
auto status = PdhEnumObjectsA(0, 0, &namebuf[0], &buflen, detail_level, FALSE);
if(status != ERROR_SUCCESS) {
return NameListParser();
}
return NameListParser(namebuf);
}
struct CounterNames { namelist_t counters, instances; };
static CounterNames ListCounters(const std::string& object_name) {
DWORD counter_list_size = 0;
DWORD instance_list_size = 0;
const DWORD detail_level = PERF_DETAIL_WIZARD;
PdhEnumObjectItemsA(0, 0, object_name.c_str(), 0, &counter_list_size, 0, &instance_list_size, detail_level, 0);
std::string counter_buf(counter_list_size, '[=10=]');
std::string inst_buf(instance_list_size, '[=10=]');
auto status = PdhEnumObjectItemsA(0, 0, object_name.c_str(), &counter_buf[0], &counter_list_size, &inst_buf[0], &instance_list_size, detail_level, 0);
if(status != ERROR_SUCCESS) {
return CounterNames();
}
auto counters = NameListParser(counter_buf);
auto instances = NameListParser(inst_buf);
return { counters, instances };
}
class Query {
struct CounterData {
PDH_HCOUNTER hcounter;
std::string name;
std::string path;
};
PDH_HQUERY hquery;
std::vector<CounterData> counter_list;
std::string object_name;
std::string instance_name;
volatile bool keep_going;
public:
Query() {
PdhOpenQuery(0, 0, &hquery) == ERROR_SUCCESS || (hquery = 0);
}
Query(const Query&) = delete;
Query(Query&& src) : hquery(src.hquery) {
src.hquery = 0;
// std::move these if you want
// this is really just for keeping hquery unique
counter_list = src.counter_list;
object_name = src.object_name;
instance_name = src.instance_name;
}
Query& operator = (const Query&) = delete;
Query& operator = (Query&& src) {
if(hquery) PdhCloseQuery(hquery);
hquery = src.hquery;
src.hquery = 0;
counter_list = src.counter_list;
object_name = src.object_name;
instance_name = src.instance_name;
return *this;
}
~Query() {
if(!hquery) return;
PdhCloseQuery(hquery);
// Counter handles belong to the query and
// don't appear to need separate closing by
// the user.
}
operator PDH_HQUERY () const { return hquery; }
bool IsOk() const { return !!hquery; }
operator const void* () const { return (const void*)IsOk(); }
void SetInstance(const std::string& name) { instance_name = name; }
void SetObject(const std::string& name) {
object_name = name;
auto counter_names = ListCounters(name);
if(counter_names.instances.size()) {
std::cout << "Automatically selecting instance \"" << counter_names.instances[0] << "\"\n";
SetInstance(counter_names.instances[0]);
}
}
static void DumpAvailableObjects() {
DumpList(ListObjectNames());
}
void DumpAvailableCounters() const {
if(object_name.empty()) {
std::cout << "DumpAvailableCounters: An object needs to be set before calling\n";
return;
}
auto counter_names = ListCounters(object_name);
DumpList(counter_names.counters);
}
void DumpAvailableInstances() const {
if(object_name.empty()) {
std::cout << "DumpAvailableInstances: An object needs to be set before calling\n";
return;
}
auto counter_names = ListCounters(object_name);
DumpList(counter_names.instances);
}
void AddCounter() {}
template <typename ...more>
void AddCounter(const std::string& name, more... args) {
if(!hquery) {
std::cout << "AddCounter: Query was not successfully created\n";
return;
}
if(object_name.empty()) {
std::cout << "AddCounter: No Object Name selected\n";
return;
}
if(instance_name.empty()) {
std::cout << "AddCounter: No Instance Name selected\n";
return;
}
CounterData counter_data;
counter_data.name = name;
counter_data.path = CounterPath(object_name, name, instance_name);
auto status = PdhAddCounterA(hquery, counter_data.path.c_str(), 0, &counter_data.hcounter);
if(status != ERROR_SUCCESS) {
std::cout << "AddCounter Failed: " << std::hex << status << '\n';
return;
}
counter_list.push_back(counter_data);
AddCounter(args...);
}
void CounterPollingDump(DWORD polling_interval_ms = 1000) {
if(counter_list.empty()) {
std::cout << "CounterPollingDump: Nothing to do, the Counter List is empty\n";
return;
}
size_t max_name_len = 0;
for(const auto& counter : counter_list) {
if(counter.name.length() > max_name_len) max_name_len = counter.name.length();
}
keep_going = true;
do {
Sleep(polling_interval_ms);
auto status = PdhCollectQueryData(hquery);
if(status != ERROR_SUCCESS) {
std::cout << "CounterPollingDump: PdhCollectQueryData failed: " << std::hex << status << '\n';
return;
}
std::cout << " =======================\n";
for(const auto& counter : counter_list) {
const std::string spaces(max_name_len-counter.name.length()+2, ' ');
std::cout << counter.name << spaces;
DWORD counter_type;
PDH_FMT_COUNTERVALUE fmt_value = {0};
auto status = PdhGetFormattedCounterValue(counter.hcounter, PDH_FMT_DOUBLE, &counter_type, &fmt_value);
if(status != ERROR_SUCCESS) {
if(status == PDH_INVALID_DATA) {
std::cout << " -- no data --\n";
continue;
}
std::cout << "CounterPollingDump: PdhGetFormattedCounterValue failed: " << std::hex << status << '\n';
return;
}
std::cout << " " << fmt_value.doubleValue << '\n';
}
} while(keep_going);
}
void StopPolling() {
keep_going = false;
}
};
int main() {
Query query;
//query.DumpAvailableObjects();
query.SetObject("Network Interface");
//query.DumpAvailableCounters();
//query.DumpAvailableInstances();
//query.SetInstance("Some Other Ethernet Device");
query.AddCounter("Bytes Received/sec");
query.AddCounter("Bytes Sent/sec");
query.CounterPollingDump(); // loops until you Ctrl-Break
}