c++ 获取设备连接的网络打印机设备信息
以下是一个跨平台的C++方案,结合系统API和SNMP协议实现网络打印机信息获取:
#include <iostream>
#include <vector>
#include <string>
// 平台抽象层
#ifdef _WIN32
#include <windows.h>
#include <winsock.h>
#include <winprinter.h>
#elif defined(__linux__)
#include <cups/cups.h>
#endif
// SNMP抽象层
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
struct PrinterInfo {
std::string name;
std::string ip;
std::string mac;
std::string serial;
std::string manufacturer;
};
class PrinterEnumerator {
public:
std::vector<PrinterInfo> getNetworkPrinters() {
std::vector<PrinterInfo> printers;
// 获取基础打印机信息
#ifdef _WIN32
enumerateWindowsPrinters(printers);
#elif defined(__linux__)
enumerateLinuxPrinters(printers);
#endif
// 通过SNMP补充详细信息
for (auto& printer : printers) {
if (!printer.ip.empty()) {
querySNMPInfo(printer);
}
}
return printers;
}
private:
#ifdef _WIN32
void enumerateWindowsPrinters(std::vector<PrinterInfo>& printers) {
DWORD needed = 0;
DWORD returned = 0;
EnumPrinters(PRINTER_ENUM_NETWORK, NULL, 4, NULL, 0, &needed, &returned);
std::vector<BYTE> buffer(needed);
if (EnumPrinters(PRINTER_ENUM_NETWORK, NULL, 4, buffer.data(),
buffer.size(), &needed, &returned)) {
PRINTER_INFO_4* info = reinterpret_cast<PRINTER_INFO_4*>(buffer.data());
for (DWORD i = 0; i < returned; ++i) {
PrinterInfo pi;
pi.name = info[i].pPrinterName;
// 需要解析端口信息获取IP
parseWindowsPort(pi);
printers.push_back(pi);
}
}
}
#elif defined(__linux__)
void enumerateLinuxPrinters(std::vector<PrinterInfo>& printers) {
cups_dest_t* dests = cupsGetDests(CUPS_HTTP_DEFAULT);
for (int i = 0; i < cupsGetDests(&dests); ++i) {
PrinterInfo pi;
pi.name = dests[i].name;
// 解析设备URI获取IP
const char* uri = cupsGetOption("device-uri",
dests[i].num_options, dests[i].options);
if (uri && strstr(uri, "socket://")) {
pi.ip = extractIPFromURI(uri);
}
printers.push_back(pi);
}
cupsFreeDests(dests);
}
#endif
void querySNMPInfo(PrinterInfo& printer) {
// 公共OID查询
getSNMPValue(printer.ip, "1.3.6.1.2.1.1.1.0", printer.manufacturer);
getSNMPValue(printer.ip, "1.3.6.1.2.1.43.5.1.1.17.1", printer.serial);
// MAC地址需要接口索引,这里简化处理
std::string macHex;
if (getSNMPValue(printer.ip, "1.3.6.1.2.1.2.2.1.6.1", macHex)) {
printer.mac = formatMAC(macHex);
}
}
bool getSNMPValue(const std::string& ip, const char* oid, std::string& output) {
// SNMP实现(需包含net-snmp库)
// 此处实现与之前示例类似,需处理Windows/Linux差异
// ...
return true;
}
// 辅助函数
std::string formatMAC(const std::string& hex) {
std::string mac;
for (size_t i = 0; i < hex.length(); i += 2) {
if (!mac.empty()) mac += ":";
mac += hex.substr(i, 2);
}
return mac;
}
};
int main() {
PrinterEnumerator enumerator;
auto printers = enumerator.getNetworkPrinters();
for (const auto& p : printers) {
std::cout << "Printer: " << p.name << "\n"
<< " IP: " << p.ip << "\n"
<< " MAC: " << p.mac << "\n"
<< " Serial: " << p.serial << "\n"
<< " Manufacturer: " << p.manufacturer << "\n\n";
}
return 0;
}
实现说明
-
跨平台架构:
- 使用预处理器指令区分Windows/Linux实现
- Windows使用Win32打印API
- Linux使用CUPS API
-
信息获取流程:
graph TD A[开始] --> B[枚举网络打印机] B --> C[获取基础信息] C --> D[解析IP地址] D --> E[SNMP查询详细信息] E --> F[输出结果] -
关键组件:
- 打印机枚举:通过系统原生API获取打印机列表
- IP解析:
- Windows:解析打印机端口配置
- Linux:解析CUPS设备URI
- SNMP查询:使用net-snmp库获取详细设备信息
-
平台差异处理:
| 功能 | Windows 实现 | Linux 实现 |
|---|---|---|
| 打印机枚举 | EnumPrinters API | cupsGetDests |
| IP地址解析 | 解析端口配置注册表 | 解析CUPS设备URI |
| SNMP通信 | WinSNMP库 或 net-snmp跨平台编译 | net-snmp库 |
编译与依赖
-
Windows要求:
- 安装net-snmp Win32开发包
- 链接库:wsnmp32.lib, winsock32.lib
-
Linux要求:
sudo apt-get install libcups2-dev libsnmp-dev -
编译命令:
# Windows cl /EHsc printer_info.cpp /link wsnmp32.lib # Linux g++ -o printer_info printer_info.cpp -lcups -lnetsnmp
增强建议
-
IP地址解析增强:
#ifdef _WIN32 void parseWindowsPort(PrinterInfo& pi) { // 通过注册表解析端口配置 HKEY hKey; if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Ports", 0, KEY_READ, &hKey) == ERROR_SUCCESS) { // 解析端口配置... RegCloseKey(hKey); } } #endif -
SNMP异常处理:
bool getSNMPValue(...) { try { // SNMP实现 return true; } catch (const std::exception& e) { std::cerr << "SNMP Error: " << e.what() << std::endl; return false; } } -
厂商OID扩展:
const std::map<std::string, std::string> VENDOR_OIDS = { {"HP", "1.3.6.1.4.1.11.2.3.9.1"}, {"Canon", "1.3.6.1.4.1.1602.4.1.1.1"}, {"Epson", "1.3.6.1.4.1.1248.1.1.1.1"} };
注意事项
-
权限要求:
- Windows需要管理员权限访问注册表
- Linux需要cups权限和SNMP访问权限
-
网络配置:
- 确保打印机SNMP服务已启用(UDP 161端口)
- 可能需要配置SNMP community string
-
性能优化:
// 使用异步SNMP请求 void asyncSNMPQuery(...) { // 实现异步请求处理 } -
备用方案:
// 当SNMP不可用时尝试其他协议 void fallbackProtocolQuery(...) { // 实现LPD/JetDirect等协议查询 }
该方案通过结合系统级打印机枚举和标准SNMP协议,实现了跨平台的网络打印机信息获取。实际部署时需要根据具体网络环境和打印机型号调整OID配置,并处理不同厂商的特殊实现。

浙公网安备 33010602011771号