张洋 1 month ago
parent
commit
d2ac30c00d

+ 6 - 239
zhipuzi_pos_windows/worker/CPosPrinterWorker.cpp

@@ -3,12 +3,16 @@
 
 #include "../helper/CComHelper.h"
 
-// 在文件顶部(现有 include 之后)添加
 #include <devpkey.h>
 #include <devpropdef.h>
 
 #pragma comment(lib, "setupapi.lib")
-#pragma comment(lib, "winspool.lib")
+
+//SetupDiGetInterfaceDeviceDetail所需要的输出长度,定义足够大
+#define INTERFACE_DETAIL_SIZE 1024
+
+//USB类的GUID,通过这个去找USB打印机
+const GUID USB_GUID = { 0x28d78fad, 0x5a12, 0x11d1, {0xae, 0x5b, 0x00, 0x00, 0xf8, 0x03, 0xa8, 0xc2 } };
 
 // 本地定义 DEVPROPKEY,等价于 DEVPKEY_Device_BusReportedDeviceDesc (fmtid + pid=4)
 const DEVPROPKEY PKEY_Device_BusReportedDeviceDesc_local =
@@ -17,243 +21,6 @@ const DEVPROPKEY PKEY_Device_BusReportedDeviceDesc_local =
 	4
 };
 
-// Helper: case-insensitive find
-static bool ci_find_substr(const std::wstring& hay, const std::wstring& needle)
-{
-	if (needle.empty()) return false;
-	std::wstring h = hay, n = needle;
-	for (auto& c : h) c = towlower(c);
-	for (auto& c : n) c = towlower(c);
-	return h.find(n) != std::wstring::npos;
-}
-
-// 读取系统已安装打印机(PRINTER_INFO_2),返回 vector of printer names and port names
-static std::vector<std::pair<std::wstring, std::wstring>> EnumerateInstalledPrinters()
-{
-	std::vector<std::pair<std::wstring, std::wstring>> res;
-
-	DWORD needed = 0, returned = 0;
-	EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, 2, NULL, 0, &needed, &returned);
-	if (needed == 0) return res;
-
-	std::vector<BYTE> buffer(needed);
-	if (!EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, 2, buffer.data(), needed, &needed, &returned))
-	{
-		LOG_INFO("EnumerateInstalledPrinters: EnumPrinters failed err=" << GetLastError());
-		return res;
-	}
-
-	PRINTER_INFO_2W* p = reinterpret_cast<PRINTER_INFO_2W*>(buffer.data());
-	for (DWORD i = 0; i < returned; ++i)
-	{
-		std::wstring name = p[i].pPrinterName ? p[i].pPrinterName : L"";
-		std::wstring port = p[i].pPortName ? p[i].pPortName : L"";
-		res.emplace_back(name, port);
-		LOG_INFO(L"InstalledPrinter: Name=" << name << L", Port=" << port);
-	}
-
-	return res;
-}
-
-// 从 DevicePath 提取 vid/pid
-static void ExtractVidPidFromDevicePath(const std::wstring& devicePath, std::wstring& outVid, std::wstring& outPid)
-{
-	outVid.clear(); outPid.clear();
-	size_t posVid = devicePath.find(L"vid_");
-	size_t posPid = devicePath.find(L"pid_");
-	if (posVid != std::wstring::npos && posVid + 4 + 4 <= devicePath.length())
-		outVid = devicePath.substr(posVid + 4, 4);
-	if (posPid != std::wstring::npos && posPid + 4 + 4 <= devicePath.length())
-		outPid = devicePath.substr(posPid + 4, 4);
-}
-
-// 给定 DevicePath,尝试读取该设备的 BusReportedDeviceDesc、FriendlyName/DeviceDesc、Location 信息等
-static void QueryUsbDeviceDetailsByPath(const std::wstring& targetDevicePath,
-	std::wstring& outBusReported, std::wstring& outRegName, std::wstring& outLocation)
-{
-	outBusReported.clear();
-	outRegName.clear();
-	outLocation.clear();
-
-	// 枚举 GUID 为 USB GUID 的设备并查找与 targetDevicePath 匹配的那个
-	HDEVINFO hDevInfoSet = ::SetupDiGetClassDevs((LPGUID)&USB_GUID, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
-	if (hDevInfoSet == INVALID_HANDLE_VALUE) return;
-
-	PSP_DEVICE_INTERFACE_DETAIL_DATA pDetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)::GlobalAlloc(LMEM_ZEROINIT, INTERFACE_DETAIL_SIZE);
-	if (!pDetail)
-	{
-		SetupDiDestroyDeviceInfoList(hDevInfoSet);
-		return;
-	}
-	pDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
-
-	SP_DEVINFO_DATA devInfo = {};
-	SP_DEVICE_INTERFACE_DATA ifData = {};
-	devInfo.cbSize = sizeof(SP_DEVINFO_DATA);
-	ifData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
-
-	for (DWORD idx = 0; ; ++idx)
-	{
-		if (!SetupDiEnumDeviceInfo(hDevInfoSet, idx, &devInfo)) break;
-
-		ifData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
-		if (!SetupDiEnumDeviceInterfaces(hDevInfoSet, NULL, (LPGUID)&USB_GUID, idx, &ifData))
-			continue;
-
-		if (!SetupDiGetInterfaceDeviceDetail(hDevInfoSet, &ifData, pDetail, INTERFACE_DETAIL_SIZE, NULL, &devInfo))
-			continue;
-
-		std::wstring devPath = pDetail->DevicePath;
-		if (devPath != targetDevicePath) continue; // 未匹配则继续
-
-		// 找到目标设备,读取注册表描述
-		DWORD propType = 0, req = 0;
-		WCHAR buf[MAX_PATH] = { 0 };
-		if (SetupDiGetDeviceRegistryProperty(hDevInfoSet, &devInfo, SPDRP_FRIENDLYNAME, &propType, (PBYTE)buf, sizeof(buf), &req))
-		{
-			outRegName = buf;
-		}
-		else if (SetupDiGetDeviceRegistryProperty(hDevInfoSet, &devInfo, SPDRP_DEVICEDESC, &propType, (PBYTE)buf, sizeof(buf), &req))
-		{
-			outRegName = buf;
-		}
-
-		// 尝试读取 BusReportedDeviceDesc(Product string)
-		{
-			DEVPROPTYPE devPropType = 0;
-			DWORD required = 0;
-			WCHAR smallBuf[256] = { 0 };
-			if (SetupDiGetDevicePropertyW(hDevInfoSet, &devInfo, &PKEY_Device_BusReportedDeviceDesc_local, &devPropType,
-				reinterpret_cast<PBYTE>(smallBuf), sizeof(smallBuf), &required, 0))
-			{
-				outBusReported = smallBuf;
-			}
-			else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER && required > 0)
-			{
-				std::vector<BYTE> bigBuf(required);
-				if (SetupDiGetDevicePropertyW(hDevInfoSet, &devInfo, &PKEY_Device_BusReportedDeviceDesc_local, &devPropType,
-					bigBuf.data(), required, &required, 0))
-				{
-					outBusReported.assign(reinterpret_cast<WCHAR*>(bigBuf.data()));
-				}
-			}
-		}
-
-		// 读取位置/端口信息(LocationInformation)
-		{
-			DWORD required = 0;
-			WCHAR locBuf[256] = { 0 };
-			if (SetupDiGetDeviceRegistryProperty(hDevInfoSet, &devInfo, SPDRP_LOCATION_INFORMATION, &propType, (PBYTE)locBuf, sizeof(locBuf), &required))
-			{
-				outLocation = locBuf;
-			}
-		}
-
-		break; // 找到并读取后退出
-	}
-
-	::GlobalFree(pDetail);
-	::SetupDiDestroyDeviceInfoList(hDevInfoSet);
-}
-
-// 主映射函数实现
-std::vector<UsbPrinterMapping> CPosPrinterWorker::MapUsbDevicesToInstalledPrinters()
-{
-	std::vector<UsbPrinterMapping> result;
-
-	// 1) 枚举已安装的打印机(名字 + 端口),用于后续匹配
-	auto printers = EnumerateInstalledPrinters();
-
-	// 2) 取得系统检测到的 USB 设备 DevicePath 列表(使用现有接口)
-	std::vector<std::wstring> usbDevices = CPosPrinterWorker::GetInstance()->getUsbDevices();
-
-	LOG_INFO("MapUsbDevicesToInstalledPrinters: usbDevices count=" << usbDevices.size());
-
-	// 3) 对每个 DevicePath 查询更多信息并尝试匹配
-	for (const auto& dp : usbDevices)
-	{
-		UsbPrinterMapping item;
-		item.devicePath = dp;
-		ExtractVidPidFromDevicePath(dp, item.vid, item.pid);
-
-		// 读取 BusReported, regName, location
-		QueryUsbDeviceDetailsByPath(dp, item.busReportedName, item.regName, item.vid /* reuse var not needed */);
-		// QueryUsbDeviceDetailsByPath fills busReportedName and regName (location ignored here)
-
-		LOG_INFO(L"DevicePath=" << dp);
-		LOG_INFO(L"  busReported=" << item.busReportedName << L", regName=" << item.regName << L", vid=" << item.vid << L", pid=" << item.pid);
-
-		// 尝试多种匹配策略(逐一尝试)
-		for (const auto& pr : printers)
-		{
-			const std::wstring& printerName = pr.first;
-			const std::wstring& portName = pr.second;
-
-			bool matched = false;
-
-			// 1) 如果 busReported 在打印机名称中(不区分大小写)
-			if (!item.busReportedName.empty() && ci_find_substr(printerName, item.busReportedName))
-			{
-				matched = true;
-			}
-
-			// 2) 如果注册表名称在打印机名称中
-			if (!matched && !item.regName.empty() && ci_find_substr(printerName, item.regName))
-			{
-				matched = true;
-			}
-
-			// 3) 如果打印机端口名包含 VID 或 PID(有些端口字符串会包含硬件id或序号)
-			if (!matched && !item.vid.empty() && ci_find_substr(portName, item.vid))
-			{
-				matched = true;
-			}
-			if (!matched && !item.pid.empty() && ci_find_substr(portName, item.pid))
-			{
-				matched = true;
-			}
-
-			// 4) 如果端口名本身等于 USB001/USB002 且注册表 location 包含相同信息,则匹配(二者需要更多自定义逻辑)
-			//    这里把端口名直接当作可能匹配项的一部分:若端口名出现在 regName/location 中则认为是匹配
-			if (!matched && !portName.empty() && (!item.regName.empty() && ci_find_substr(item.regName, portName) || !item.busReportedName.empty() && ci_find_substr(item.busReportedName, portName)))
-			{
-				matched = true;
-			}
-
-			if (matched)
-			{
-				item.matchedPrinterNames.push_back(printerName);
-				LOG_INFO(L"  Matched printer: " << printerName << L" (port=" << portName << L")");
-			}
-		}
-
-		result.push_back(item);
-	}
-
-	// 输出没有被匹配到的打印机(便于调试)
-	for (const auto& pr : printers)
-	{
-		bool used = false;
-		for (const auto& it : result)
-		{
-			for (const auto& m : it.matchedPrinterNames)
-			{
-				if (m == pr.first)
-				{
-					used = true; break;
-				}
-			}
-			if (used) break;
-		}
-		if (!used)
-		{
-			LOG_INFO(L"Installed printer not matched to any USB device: " << pr.first << L", port=" << pr.second);
-		}
-	}
-
-	return result;
-}
-
 CPosPrinterWorker::CPosPrinterWorker()
 {
 }

+ 0 - 23
zhipuzi_pos_windows/worker/CPosPrinterWorker.h

@@ -2,25 +2,6 @@
 
 #include "../print/CPosPrinterData.h"
 
-//SetupDiGetInterfaceDeviceDetail所需要的输出长度,定义足够大
-#define INTERFACE_DETAIL_SIZE 1024
-
-//设备数量上限,假设16台上限
-#define MAX_DEVICE 16
-
-//USB类的GUID,通过这个去找USB打印机
-const GUID USB_GUID = { 0x28d78fad, 0x5a12, 0x11d1, {0xae, 0x5b, 0x00, 0x00, 0xf8, 0x03, 0xa8, 0xc2 } };
-
-struct UsbPrinterMapping
-{
-	std::wstring devicePath;        // CreateFile 使用的 DevicePath
-	std::wstring busReportedName;   // 总线报告的设备描述(Product string),若能读取到
-	std::wstring regName;           // 注册表里的 FriendlyName / DeviceDesc
-	std::wstring vid;               // 从 DevicePath 提取的 VID
-	std::wstring pid;               // 从 DevicePath 提取的 PID
-	std::vector<std::wstring> matchedPrinterNames; // 匹配到的打印队列名称(EnumPrinters)
-};
-
 //这个类采用队列的模式,执行把数据发送给打印机,注意这个类只负责发送,不负责数据内容的组装
 class CPosPrinterWorker
 {
@@ -56,10 +37,6 @@ public:
 	//获取当前电脑上所有的打印usb设备
 	std::vector<std::wstring> getUsbDevices();
 
-	/// 枚举系统已安装的打印队列并把它们与当前系统的 USB 打印设备做一次尽力匹配。、
-	/// 主要用于调试与定位:会返回每个 USB 设备的额外信息(busReported/regName/vid/pid)
-	std::vector<UsbPrinterMapping> MapUsbDevicesToInstalledPrinters();
-
 private:
 	CPosPrinterWorker();