VCMFC根據USB裝置PID、VID自動查詢串列埠號
阿新 • • 發佈:2019-01-10
在VC/MFC環境下有兩種方法來根據PID、VID獲取對應的串列埠號,這樣操作的目的是避免客戶手動設定下拉框的資訊,讓軟體自動識別!當然,前提是有自己的USB PID、VID
下面是C++程式碼示例:
// 第一種方法需要包含此標頭檔案 #include <SetupAPI.h> #pragma comment(lib, "Setupapi.lib") #define MY_USB_PID_VID _T("VID_1111&PID_2222") /************************************************************************/ /* 根據USB描述資訊字串中讀取 /************************************************************************/ int MTGetPortFromVidPid(CString strVidPid) { // 獲取當前系統所有使用的裝置 int nPort = -1; int nStart = -1; int nEnd = -1; int i = 0; CString strTemp, strName; DWORD dwFlag = (DIGCF_ALLCLASSES | DIGCF_PRESENT); HDEVINFO hDevInfo = INVALID_HANDLE_VALUE; SP_DEVINFO_DATA sDevInfoData; TCHAR szDis[MAX_PATH] = {0x00};// 儲存裝置例項ID TCHAR szFN[MAX_PATH] = {0x00};// 儲存裝置例項屬性 DWORD nSize = 0 ; // 準備遍歷所有裝置查詢USB hDevInfo = SetupDiGetClassDevs(NULL, NULL, NULL, dwFlag); if( INVALID_HANDLE_VALUE == hDevInfo ) goto STEP_END; // 開始遍歷所有裝置 memset(&sDevInfoData, 0x00, sizeof(SP_DEVICE_INTERFACE_DATA)); sDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA); for(i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &sDevInfoData); i++ ) { nSize = 0; // 無效裝置 if ( !SetupDiGetDeviceInstanceId(hDevInfo, &sDevInfoData, szDis, sizeof(szDis), &nSize) ) goto STEP_END; // 根據裝置資訊尋找VID PID一致的裝置 strTemp.Format(_T("%s"),szDis); strTemp.MakeUpper(); if ( strTemp.Find(strVidPid, 0) == -1 ) continue; // 查詢裝置屬性 nSize = 0; SetupDiGetDeviceRegistryProperty(hDevInfo, &sDevInfoData, SPDRP_FRIENDLYNAME, 0, (PBYTE) szFN, sizeof(szFN), &nSize); // "XXX Virtual Com Port (COM7)" strName.Format(_T("%s"),szFN); if(strName.IsEmpty()) goto STEP_END; // 尋找串列埠資訊 nStart = strName.Find(_T("(COM"), 0); nEnd = strName.Find(_T(")"), 0); if(nStart == -1 || nEnd == -1) goto STEP_END; strTemp = strName.Mid(nStart + 4, nEnd - nStart - 2); nPort = atoi(strTemp); } STEP_END: // 關閉裝置資訊集控制代碼 if(hDevInfo != INVALID_HANDLE_VALUE) { SetupDiDestroyDeviceInfoList(hDevInfo); hDevInfo = INVALID_HANDLE_VALUE; } return nPort; } /************************************************************************/ /* 根據登錄檔中的PID、VID資訊讀取 /************************************************************************/ int MTUpdateSerialPort(CString strVidPid) { DWORD dwIndex = 0; HKEY hKey; TCHAR CommName[_MAX_FNAME] = {0x00}; DWORD lcbName = _MAX_FNAME; DWORD lValue = MAX_PATH; TCHAR szValue[MAX_PATH]; LONG lRtn = 0; CString strTemp, strKey; int nPort = -1; int nStart = -1; int nEnd = -1; // 讀取PID對應的埠 strTemp.Format_T("SYSTEM\\CurrentControlSet\\Enum\\USB\\%s"),strVidPid); if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, strTemp, NULL, KEY_READ, &hKey) == ERROR_SUCCESS) { dwIndex = 0; while (RegEnumKey(hKey,dwIndex++,CommName,lcbName) == ERROR_SUCCESS) { // 讀取PID對應的埠 strKey.Format(_T("SYSTEM\\CurrentControlSet\\Enum\\USB\\%s\\%s\\Device Parameters"),strVidPid,CommName); RegCloseKey(hKey); if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,strKey,NULL,KEY_READ,&hKey) == ERROR_SUCCESS) { lRtn = RegQueryValueEx(hKey,_T("PortName"),NULL,&lValue,(LPBYTE)szValue,&lValue); if ( lRtn == ERROR_SUCCESS) { // 尋找串列埠資訊 strName.Format(_T("%s"),szValue); nStart = strName.Find(_T("COM"), 0); nEnd = strName.Find(_T(")"), 0); if(nStart == -1 || nEnd == -1) { RegCloseKey(hKey); return -1; } strTemp = strName.Mid(nStart + 3, nEnd - nStart); nPort = atoi(strTemp); RegCloseKey(hKey); return nPort; } } lValue = MAX_PATH; lcbName = MAX_PATH; } RegCloseKey(hKey); } return nPort; } void main() { int nPort = -1; // 第一種方法遍歷USB裝置描述 nPort = MTGetPortFromVidPid(MY_USB_PID_VID); // 第二種方法遍歷登錄檔的PID、VID屬性 nPort = MTUpdateSerialPort(MY_USB_PID_VID); if(nPort == -1) printf("未找到 %s 相關串列埠號!\n"); else printf("成功找到串列埠號:COM%d \n",nPort); }