| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903 |
- #include "pch.h"
- #include "CPosPrinterWorker.h"
- #include "../helper/CComHelper.h"
- #include <devpkey.h>
- #include <devpropdef.h>
- #pragma comment(lib, "setupapi.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 =
- {
- { 0x540b947e, 0x8b40, 0x45bc, { 0xa8, 0xa2, 0x6a, 0x0b, 0x89, 0x4c, 0xbd, 0xa2 } },
- 4
- };
- CPosPrinterWorker::CPosPrinterWorker()
- {
- }
- void CPosPrinterWorker::Start()
- {
- m_is_work = true;
- //处理收银打印
- std::thread(&CPosPrinterWorker::HandleShouyinPrinter, this).detach();
- //处理标签打印
- std::thread(&CPosPrinterWorker::HandleBiaoqianPrinter, this).detach();
- //处理厨房打印
- std::thread(&CPosPrinterWorker::HandleChufangPrinter, this).detach();
- }
- void CPosPrinterWorker::Stop()
- {
- m_is_work = false;
- }
- void CPosPrinterWorker::AddShouyinPrinter(std::string chufang_data)
- {
- std::lock_guard<std::mutex> lock(m_shouyin_printer_mutex);
- m_shouyin_printer_queue.push(chufang_data);
- }
- void CPosPrinterWorker::AddBiaoqianPrinter(std::string data)
- {
- std::lock_guard<std::mutex> lock(m_biaoqian_printer_mutex);
- m_biaoqian_printer_queue.push(data);
- }
- void CPosPrinterWorker::AddChufangPrinter(ChufangPrinterContent data)
- {
- std::lock_guard<std::mutex> lock(m_chufang_printer_mutex);
- m_chufang_printer_queue.push(data);
- }
- void CPosPrinterWorker::HandleShouyinPrinter()
- {
- while (m_is_work)
- {
- std::string data;
- {
- std::lock_guard<std::mutex> lock(m_shouyin_printer_mutex);
- if (m_shouyin_printer_queue.empty())
- {
- data.clear();
- }
- else
- {
- data = m_shouyin_printer_queue.front();
- }
- }
- if (data.empty())
- {
- Sleep(100);
- continue;
- }
- if (SendDataToShouyinPirnter(data))
- {
- std::lock_guard<std::mutex> lock(m_shouyin_printer_mutex);
- if (!m_shouyin_printer_queue.empty() && m_shouyin_printer_queue.front() == data)
- {
- m_shouyin_printer_queue.pop();
- }
- }
- else
- {
- Sleep(1000);
- }
- }
- }
- void CPosPrinterWorker::HandleBiaoqianPrinter()
- {
- while (m_is_work)
- {
- std::string data;
- {
- std::lock_guard<std::mutex> lock(m_biaoqian_printer_mutex);
- if (m_biaoqian_printer_queue.empty())
- {
- data.clear();
- }
- else
- {
- data = m_biaoqian_printer_queue.front();
- }
- }
- if (data.empty())
- {
- Sleep(100);
- continue;
- }
- if (SendDataToBiaoqianPirnter(data))
- {
- std::lock_guard<std::mutex> lock(m_biaoqian_printer_mutex);
- if (!m_biaoqian_printer_queue.empty() && m_biaoqian_printer_queue.front() == data)
- {
- m_biaoqian_printer_queue.pop();
- }
- }
- else
- {
- Sleep(1000);
- }
- }
- }
- void CPosPrinterWorker::HandleChufangPrinter()
- {
- while (m_is_work)
- {
- ChufangPrinterContent chufang_data;
- bool hasData = false;
- {
- std::lock_guard<std::mutex> lock(m_chufang_printer_mutex);
- if (!m_chufang_printer_queue.empty())
- {
- chufang_data = m_chufang_printer_queue.front();
- hasData = true;
- }
- }
- if (!hasData)
- {
- Sleep(100);
- continue;
- }
- if (SendDataToChufangPirnter(chufang_data))
- {
- std::lock_guard<std::mutex> lock(m_chufang_printer_mutex);
- if (!m_chufang_printer_queue.empty())
- {
- m_chufang_printer_queue.pop();
- }
- }
- else
- {
- Sleep(1000);
- }
- }
- }
- bool CPosPrinterWorker::SendDataToShouyinPirnter(std::string data)
- {
- bool bSuccess = false;
- //默认是句柄模式
- int nType = 1;
- //用于厨房打印机和网口类型的收银小票打印
- boost::asio::io_context m_io;
- boost::asio::ip::tcp::socket m_socket(m_io);
- std::string printer_leixing = CSetting::GetInstance()->GetParam("setting_printer_leixing");
- if (printer_leixing == "auto")
- {
- InitUsb();
- InitBingkou();
- InitCom();
- if (m_hShouyinPorts.size() == 0)
- {
- return false;
- }
- }
- else if (printer_leixing == "usb")
- {
- std::string printer_usb = CSetting::GetInstance()->GetParam("setting_printer_usb");
- std::wstring ws_printer_usb = CLewaimaiString::UTF8ToUnicode(printer_usb);
- bool ret = InitOneUsb(ws_printer_usb, 1);
- if (ret == false)
- {
- return false;
- }
- }
- else if (printer_leixing == "bingkou")
- {
- bool ret = InitBingkou();
- if (ret == false)
- {
- return false;
- }
- }
- else if (printer_leixing == "chuankou")
- {
- InitCom();
- }
- else if (printer_leixing == "wangkou")
- {
- //改为网口模式
- nType = 2;
- std::string wangkou_ip = CSetting::GetInstance()->GetParam("setting_printer_wangkou_ip");
- //初始化连接
- try
- {
- boost::asio::ip::tcp::endpoint ep(boost::asio::ip::make_address(wangkou_ip.c_str()), 9100);
- m_socket.connect(ep);
- }
- catch (std::exception& e)
- {
- std::string err = e.what();
- LOG_INFO("网口打印机连接失败,IP地址:" << wangkou_ip.c_str() << ",错误信息:" << err.c_str());
- MessageBoxW(NULL, (L"小票网口打印机连接失败,IP地址:" + CLewaimaiString::UTF8ToUnicode(wangkou_ip)).c_str(), L"打印机连接失败", MB_OK);
- return false;
- }
- }
- //开始发送数据
- if (nType == 1)
- {
- bSuccess = true;
- //USB、串口、并口,走这里
- for (std::vector<HANDLE>::iterator it = m_hShouyinPorts.begin(); it != m_hShouyinPorts.end(); it++)
- {
- HANDLE hPort = *it;
- //同步写数据
- DWORD dwWrite = 0;
- bool ret = WriteWithTimeout(hPort, data.c_str(), (DWORD)data.length(), 5000, dwWrite);
- if (!ret || dwWrite != (DWORD)data.length())
- {
- LOG_INFO("WriteWithTimeout Failed or partial write!, hPort:" << hPort << ", dwWrite:" << dwWrite);
- bSuccess = false;
- break;
- }
- }
- }
- else
- {
- //网口走这里
- try
- {
- boost::asio::write(m_socket, boost::asio::buffer(data.c_str(), data.length()));
- bSuccess = true;
- }
- catch (const std::exception& e)
- {
- LOG_INFO("网口打印机发送消息失败,错误信息:" << e.what());
- bSuccess = false;
- }
- }
- //关闭设备
- for (std::vector<HANDLE>::iterator it = m_hShouyinPorts.begin(); it != m_hShouyinPorts.end(); it++)
- {
- CloseHandle(*it);
- }
- //删除之前旧的句柄
- m_hShouyinPorts.clear();
- if (nType == 2)
- {
- m_socket.close();
- }
- return bSuccess;
- }
- bool CPosPrinterWorker::SendDataToBiaoqianPirnter(std::string data)
- {
- bool bSuccess = false;
- //默认是句柄模式
- int nType = 1;
-
- //用于厨房打印机和网口类型的收银小票打印
- boost::asio::io_context m_io;
- boost::asio::ip::tcp::socket m_socket(m_io);
- std::string printer_leixing = CSetting::GetInstance()->GetParam("setting_biaoqian_printer_leixing");
- if (printer_leixing == "usb")
- {
- std::string printer_usb = CSetting::GetInstance()->GetParam("setting_biaoqian_printer_usb");
- std::wstring ws_printer_usb = CLewaimaiString::UTF8ToUnicode(printer_usb);
- //连接usb端口
- bool ret = InitOneUsb(ws_printer_usb, 2);
- if (ret == false)
- {
- return false;
- }
- }
- else if (printer_leixing == "wangkou")
- {
- //改为网口模式
- nType = 2;
- std::string wangkou_ip = CSetting::GetInstance()->GetParam("setting_biaoqian_printer_wangkou_ip");
- //初始化连接
- try
- {
- boost::asio::ip::tcp::endpoint ep(boost::asio::ip::make_address(wangkou_ip.c_str()), 9100);
- m_socket.connect(ep);
- }
- catch (std::exception& e)
- {
- std::string err = e.what();
- LOG_INFO("网口打印机连接失败,IP地址:" << wangkou_ip.c_str() << ",错误信息:" << err.c_str());
- MessageBoxW(NULL, (L"标签网口打印机连接失败,IP地址:" + CLewaimaiString::UTF8ToUnicode(wangkou_ip)).c_str(), L"打印机连接失败", MB_OK);
- return false;
- }
- }
- //开始发送数据
- if (nType == 1)
- {
- //USB、串口、并口,走这里
- for (std::vector<HANDLE>::iterator it = m_hBiaoqianPorts.begin(); it != m_hBiaoqianPorts.end(); it++)
- {
- HANDLE hPort = *it;
-
- //同步写数据
- DWORD dwWrite = 0;
- bool ret = WriteWithTimeout(hPort, data.c_str(), (DWORD)data.length(), 5000, dwWrite);
- if (!ret || dwWrite != (DWORD)data.length())
- {
- LOG_INFO("WriteWithTimeout Failed or partial write!, hPort:" << hPort << ", dwWrite:" << dwWrite);
- bSuccess = false;
- break;
- }
- }
- }
- else
- {
- //网口走这里
- try
- {
- boost::asio::write(m_socket, boost::asio::buffer(data.c_str(), data.length()));
- bSuccess = true;
- }
- catch (const std::exception& e)
- {
- LOG_INFO("网口打印机发送消息失败,错误信息:" << e.what());
- bSuccess = false;
- }
- }
- //关闭设备
- for (std::vector<HANDLE>::iterator it = m_hBiaoqianPorts.begin(); it != m_hBiaoqianPorts.end(); it++)
- {
- CloseHandle(*it);
- }
- m_hBiaoqianPorts.clear();
- if (nType == 2)
- {
- m_socket.close();
- }
- return bSuccess;
- }
- bool CPosPrinterWorker::SendDataToChufangPirnter(ChufangPrinterContent chufang_data)
- {
- bool bSuccess = false;
- boost::asio::io_context m_io;
- boost::asio::ip::tcp::socket m_socket(m_io);
- //读取厨房打印机信息
- std::vector<ChufangPrinter> total_printers = CSetting::GetInstance()->getChufangPrints();
- std::string ip = chufang_data.ip;
- std::string data = chufang_data.data;
- //初始化连接
- try
- {
- boost::asio::ip::tcp::endpoint ep(boost::asio::ip::make_address(ip.c_str()), 9100);
- m_socket.connect(ep);
- }
- catch (std::exception& e)
- {
- std::string err = e.what();
- LOG_INFO("厨房网口打印机连接失败,IP地址:" << ip.c_str() << ",错误信息:" << err.c_str());
- MessageBoxW(NULL, (L"厨房网口打印机连接失败,IP地址:" + CLewaimaiString::UTF8ToUnicode(ip)).c_str(), L"打印机连接失败", MB_OK);
- //连接失败了,处理下一个厨房打印机
- return false;
- }
- //网口走这里
- try
- {
- boost::asio::write(m_socket, boost::asio::buffer(data.c_str(), data.length()));
- bSuccess = true;
- }
- catch (const std::exception& e)
- {
- LOG_INFO("网口打印机发送消息失败,错误信息:" << e.what());
- bSuccess = false;
- }
- m_socket.close();
- return bSuccess;
- }
- //自动识别用于收银小票的USB打印机列表
- void CPosPrinterWorker::InitUsb()
- {
- //设置中文字符
- setlocale(LC_CTYPE, "chs");
- //取设备路径
- m_usb_devices.clear();
- int nDevice = GetDevicePath((LPGUID)&USB_GUID, m_usb_devices);
- LOG_INFO("可用的USB打印机数量:" << nDevice);
- //添加usb端口
- int i = 0;
- while (i < nDevice)
- {
- std::string setting_biaoqian_printer_usb = CSetting::GetInstance()->GetParam("setting_biaoqian_printer_usb");
- std::wstring ws_setting_biaoqian_printer_usb = CLewaimaiString::UTF8ToUnicode(setting_biaoqian_printer_usb);
- if (CSetting::GetInstance()->GetParam("setting_is_new_waimai_biaoqian_printer") == "1" && ws_setting_biaoqian_printer_usb == m_usb_devices[i])
- {
- //碰到了一个在设置中心明确设置的标签打印机,过滤掉
- i++;
- continue;
- }
- LOG_INFO("准备打开端口 Port = " << m_usb_devices[i].c_str());
- HANDLE hPort = CreateFile(m_usb_devices[i].c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
- if (hPort == INVALID_HANDLE_VALUE)
- {
- LOG_INFO("打开USB端口失败, Port = " << m_usb_devices[i].c_str());
- // 打开端口失败
- DWORD error = GetLastError();
- if (error == 2)
- {
- //没有指定的文件
- LOG_INFO("没有找对对应的usb端口");
- }
- else if (error == 5)
- {
- LOG_INFO("usb端口被占用!");
- }
- i++;
- continue;
- }
- LOG_INFO("打开usb端口成功,准备进行打印机检测! hPort:" << hPort);
- m_hShouyinPorts.push_back(hPort);
- i++;
- }
- //清空usb集合,下一次调用这个函数的时候会重新设置
- m_usb_devices.clear();
- }
- bool CPosPrinterWorker::InitOneUsb(std::wstring usb_path, int nType)
- {
- if (usb_path == L"")
- {
- return false;
- }
- HANDLE hPort = CreateFile(usb_path.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
- if (hPort == INVALID_HANDLE_VALUE)
- {
- LOG_INFO("打开USB端口失败, Port = " << usb_path.c_str());
- // 打开端口失败
- DWORD error = GetLastError();
- if (error == 2)
- {
- //没有指定的文件
- LOG_INFO("没有找对对应的usb端口");
- }
- else if (error == 5)
- {
- LOG_INFO("usb端口被占用!");
- }
- return false;
- }
- LOG_INFO("打开usb端口,准备进行打印机检测! hPort:" << hPort);
- if (nType == 1)
- {
- m_hShouyinPorts.push_back(hPort);
- }
- else
- {
- m_hBiaoqianPorts.push_back(hPort);
- }
- return true;
- }
- bool CPosPrinterWorker::InitBingkou()
- {
- std::wstring LptStr = L"lpt1";
- HANDLE hPort = CreateFile(LptStr.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
- if (hPort == INVALID_HANDLE_VALUE)
- {
- LOG_INFO("打开并口失败, Port = " << LptStr.c_str());
- DWORD error = GetLastError();
- if (error == 2)
- {
- //没有指定的文件
- LOG_INFO("本机器没有并口!");
- }
- else if (error == 5)
- {
- LOG_INFO("并口被占用!");
- }
- return false;
- }
- else
- {
- //这个表示并口可以使用
- LOG_INFO("找到并口,准备进行打印机检测! hPort:" << hPort);
- m_hShouyinPorts.push_back(hPort);
- }
- return true;
- }
- void CPosPrinterWorker::InitCom()
- {
- CComHelper helper;
- std::vector<std::wstring> comVector = helper.getComPort();
- for (std::vector<std::wstring>::iterator it = comVector.begin(); it != comVector.end(); it++)
- {
- std::wstring com2Str = *it;
- HANDLE hPort = CreateFile(com2Str.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
- if (hPort == INVALID_HANDLE_VALUE)
- {
- DWORD error = GetLastError();
- if (error == 2)
- {
- //没有指定的文件
- LOG_INFO("没有找到对应的串口 " << com2Str.c_str());
- }
- else if (error == 5)
- {
- LOG_INFO("串口被占用 " << com2Str.c_str());
- }
- }
- else
- {
- LOG_INFO(com2Str.c_str() << " success, handle:" << hPort);
- //扎到了可用的串口,设置串口波特率
- DCB dcb;
- dcb.DCBlength = sizeof(dcb);
- GetCommState(hPort, &dcb);
- //佳博的串口打印机,默认是这个波特率
- dcb.BaudRate = 19200;
- if (!SetCommState(hPort, &dcb))
- {
- LOG_INFO("set baudRate failed!");
- CloseHandle(hPort);
- continue;
- }
- //设定通讯端口超时参数
- COMMTIMEOUTS tmouts;
- tmouts.ReadIntervalTimeout = 100;
- tmouts.ReadTotalTimeoutMultiplier = 100;
- tmouts.ReadTotalTimeoutConstant = 100;
- tmouts.WriteTotalTimeoutConstant = 100;
- tmouts.WriteTotalTimeoutMultiplier = 100;
- SetCommTimeouts(hPort, &tmouts);
- //设置端口缓冲
- SetupComm(hPort, 1024, 1024);
- //清除通讯端口缓存
- PurgeComm(hPort, PURGE_TXCLEAR | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_RXABORT);
- m_hShouyinPorts.push_back(hPort);
- }
- }
- }
- /*
- *获取CreateFile的USB端口号
- **/
- int CPosPrinterWorker::GetDevicePath(LPGUID lpGuid, std::vector<std::wstring>& usb_devices)
- {
- // 返回找到的设备数量
- int nCount = 0;
- // GUID 相关设备信息集句柄
- HDEVINFO hDevInfoSet = ::SetupDiGetClassDevs(lpGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
- if (hDevInfoSet == INVALID_HANDLE_VALUE)
- {
- LOG_INFO("SetupDiGetClassDevs failed");
- return 0;
- }
- // 为接口细节分配缓冲
- PSP_DEVICE_INTERFACE_DETAIL_DATA pDetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)::GlobalAlloc(LMEM_ZEROINIT, INTERFACE_DETAIL_SIZE);
- if (pDetail == NULL)
- {
- LOG_INFO("GlobalAlloc pDetail failed");
- ::SetupDiDestroyDeviceInfoList(hDevInfoSet);
- return 0;
- }
- pDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
- // 用于枚举设备信息
- SP_DEVINFO_DATA spDevInfoData = {};
- SP_DEVICE_INTERFACE_DATA ifData = {};
- spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
- ifData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
- // 用于识别通用 USB 打印类的字符串(中文/英文)
- std::wstring strUSBPrint = L"USB 打印支持";
- std::wstring strUSBPrint_EN = L"USB Printing Support";
- // 枚举设备信息条目(按索引)
- for (DWORD idx = 0; ; ++idx)
- {
- // 枚举设备信息项
- BOOL ok = ::SetupDiEnumDeviceInfo(hDevInfoSet, idx, &spDevInfoData);
- if (!ok)
- {
- // 结束或出错(当没有更多项时返回 FALSE)
- break;
- }
- // 先尝试从注册表获取 FriendlyName / DeviceDesc 作为回退名字
- TCHAR regBuf[MAX_PATH] = { 0 };
- DWORD propType = 0;
- DWORD requiredSize = 0;
- std::wstring regName;
- if (SetupDiGetDeviceRegistryProperty(hDevInfoSet, &spDevInfoData, SPDRP_FRIENDLYNAME, &propType,
- (PBYTE)regBuf, sizeof(regBuf), &requiredSize))
- {
- regName = regBuf;
- }
- else if (SetupDiGetDeviceRegistryProperty(hDevInfoSet, &spDevInfoData, SPDRP_DEVICEDESC, &propType,
- (PBYTE)regBuf, sizeof(regBuf), &requiredSize))
- {
- regName = regBuf;
- }
- else
- {
- regName = L"Unknown";
- }
- // 尝试读取总线报告的设备描述(通常为 USB Product string)
- std::wstring busReported;
- {
- DEVPROPTYPE devPropType = 0;
- DWORD req = 0;
- WCHAR smallBuf[256] = { 0 };
- BOOL got = FALSE;
- // 使用本地定义的 DEVPROPKEY:PKEY_Device_BusReportedDeviceDesc_local(需在文件顶部定义)
- if (SetupDiGetDevicePropertyW(hDevInfoSet, &spDevInfoData, &PKEY_Device_BusReportedDeviceDesc_local, &devPropType,
- reinterpret_cast<PBYTE>(smallBuf), sizeof(smallBuf), &req, 0))
- {
- busReported = smallBuf;
- got = TRUE;
- }
- else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER && req > 0)
- {
- std::vector<BYTE> bigBuf(req);
- if (SetupDiGetDevicePropertyW(hDevInfoSet, &spDevInfoData, &PKEY_Device_BusReportedDeviceDesc_local, &devPropType,
- bigBuf.data(), req, &req, 0))
- {
- // bigBuf 存储为 WCHAR 字符串
- busReported.assign(reinterpret_cast<WCHAR*>(bigBuf.data()));
- got = TRUE;
- }
- }
- if (got)
- {
- LOG_INFO(L"BusReportedDeviceDesc: " << busReported);
- }
- }
- // 如果既不是通用打印类也没有 busReported 描述,跳过该设备
- if (regName != strUSBPrint && regName != strUSBPrint_EN && busReported.empty())
- {
- LOG_INFO(L"not good usb, regName:" << regName);
- continue;
- }
- // 枚举该设备的信息接口以取得 DevicePath
- ifData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
- if (!::SetupDiEnumDeviceInterfaces(hDevInfoSet, NULL, lpGuid, idx, &ifData))
- {
- LOG_INFO("SetupDiEnumDeviceInterfaces failed for idx=" << idx);
- continue;
- }
- // 取得接口细节(包含 DevicePath)
- if (!SetupDiGetInterfaceDeviceDetail(hDevInfoSet, &ifData, pDetail, INTERFACE_DETAIL_SIZE, NULL, NULL))
- {
- LOG_INFO("SetupDiGetInterfaceDeviceDetail failed for idx=" << idx);
- continue;
- }
- std::wstring DevicePath = pDetail->DevicePath;
- // 从 DevicePath 中提取 vid/pid 以便后续判断或使用 WinUSB
- std::wstring vid = L"";
- std::wstring pid = L"";
- size_t posVid = DevicePath.find(L"vid_");
- size_t posPid = DevicePath.find(L"pid_");
- if (posVid != std::wstring::npos && posVid + 4 + 4 <= DevicePath.length()) vid = DevicePath.substr(posVid + 4, 4);
- if (posPid != std::wstring::npos && posPid + 4 + 4 <= DevicePath.length()) pid = DevicePath.substr(posPid + 4, 4);
- LOG_INFO("Vid:" << vid.c_str() << ", Pid:" << pid.c_str());
- // 输出检测到的名称(优先 busReported,其次注册表名)
- if (!busReported.empty())
- {
- LOG_INFO(L"Detected printer name: " << busReported);
- }
- else
- {
- LOG_INFO(L"Detected registry name: " << regName);
- }
- // 将 DevicePath 添加到结果集合
- usb_devices.push_back(DevicePath);
- ++nCount;
- LOG_INFO("Cnt = " << nCount << ", pDetail->DevicePath =" << pDetail->DevicePath);
- }
- // 清理并返回
- ::GlobalFree(pDetail);
- ::SetupDiDestroyDeviceInfoList(hDevInfoSet);
- return nCount;
- }
- std::vector<std::wstring> CPosPrinterWorker::getUsbDevices()
- {
- std::vector<std::wstring> usb_devices;
- int nDevice = GetDevicePath((LPGUID)&USB_GUID, usb_devices);
- return usb_devices;
- }
- bool CPosPrinterWorker::WriteWithTimeout(HANDLE hPort, const void* buffer, DWORD bufferSize, DWORD timeoutMs, DWORD& dwWrite)
- {
- dwWrite = 0;
- OVERLAPPED ov = {};
- ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- if (ov.hEvent == NULL)
- {
- return false;
- }
- BOOL ret = WriteFile(hPort, buffer, bufferSize, NULL, &ov);
- if (!ret)
- {
- DWORD err = GetLastError();
- if (err == ERROR_IO_PENDING)
- {
- DWORD waitRet = WaitForSingleObject(ov.hEvent, timeoutMs);
- if (waitRet == WAIT_OBJECT_0)
- {
- ret = GetOverlappedResult(hPort, &ov, &dwWrite, FALSE);
- }
- else
- {
- CancelIoEx(hPort, &ov);
- ret = FALSE;
- }
- }
- else
- {
- ret = FALSE;
- }
- }
- else
- {
- ret = GetOverlappedResult(hPort, &ov, &dwWrite, TRUE);
- }
- CloseHandle(ov.hEvent);
- return ret == TRUE;
- }
- bool CPosPrinterWorker::ReadWithTimeout(HANDLE hPort, void* buffer, DWORD bufferSize, DWORD timeoutMs, DWORD& dwRead)
- {
- dwRead = 0;
- OVERLAPPED ov = {};
- ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- if (ov.hEvent == NULL)
- {
- return false;
- }
- BOOL ret = ReadFile(hPort, buffer, bufferSize, NULL, &ov);
- if (!ret)
- {
- DWORD err = GetLastError();
- if (err == ERROR_IO_PENDING)
- {
- DWORD waitRet = WaitForSingleObject(ov.hEvent, timeoutMs);
- if (waitRet == WAIT_OBJECT_0)
- {
- ret = GetOverlappedResult(hPort, &ov, &dwRead, FALSE);
- }
- else
- {
- CancelIoEx(hPort, &ov);
- ret = FALSE;
- }
- }
- else
- {
- ret = FALSE;
- }
- }
- else
- {
- ret = GetOverlappedResult(hPort, &ov, &dwRead, TRUE);
- }
- CloseHandle(ov.hEvent);
- return ret == TRUE;
- }
|