通過Windows登錄檔獲取U盤、行動硬碟和USB讀卡器等裝置的PID、VID和序列號
阿新 • • 發佈:2019-02-15
當U盤、行動硬碟和USB讀卡器等裝置插入計算機USB介面,Windows會對其進行解析和相關資料記錄,這也是為什麼很多裝置第一次插入計算機時需要較長的時間識別、安裝驅動後,才會出現碟符,而第二次插入則識別速度快了很多。這些裝置的相關資訊記錄在Windows的登錄檔中,即使將裝置拔出,一些資訊仍將遺留在登錄檔中。
本文方法通過登錄檔可以的獲取當前插入計算機的U盤、行動硬碟和USB讀卡器等裝置的PID、VID和序列號,這些資訊可以用於標識裝置和對裝置進行下一步動作,如彈出裝置需要PID和VID。從原理上講,USB儲存類裝置插入當前系統時,會在Windows登錄檔如下目錄中進行登記:KEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\USBSTOR\Enum,在其Count項中記錄當前插入裝置的個數,對應的0、1、2、...表項的鍵值就記錄這響應裝置的資訊,這個序號是根據裝置插入系統的先後順序遞增記錄的,具體如下圖:
通過程式設計程式碼可以訪問該資料項,進行解析即可,一般當前插入的裝置應該排在序號的最後一位。具體流程如下,程式碼測試環境為VS2010,獲取Windows相關資料,還是用微軟的IDE和介面比較方便一些。
1、 通過訊息機制捕獲插入USB埠的儲存裝置的事件,可參考博主之前的一篇文章:
http://blog.csdn.net/trustbo/article/details/50053229 點選開啟連結
2、訪問登錄檔獲取資訊,程式碼如下:
char lpRegPath[512] = { 0 }; char lpRegValue[256] = { 0 }; sprintf(lpRegPath, "SYSTEM\\CurrentControlSet\\services\\USBSTOR\\Enum"); sprintf(lpRegValue, "Count"); // DWORD dwDataSize(0); DWORD dwRegType1(REG_DWORD); DWORD dwRegType2(REG_SZ); LPBYTE lpRegDwordData(NULL); LPBYTE lpRegSzData(NULL); // 查詢登錄檔中對映驅動器的裝置資訊 HKEY hKey; long lRet; try { lRet = ::RegOpenKeyEx( HKEY_LOCAL_MACHINE, // root key lpRegPath, // 要訪問的鍵的位置 0, // KEY_READ, // 以查詢的方式訪問登錄檔 &hKey); // hKEY儲存此函式所開啟的鍵的控制代碼 } catch(...) { return false; } if(lRet != ERROR_SUCCESS) return false; else { try { lRet = ::RegQueryValueEx(hKey, // 所開啟的鍵的控制代碼 lpRegValue, // 要查詢的鍵值名 NULL, &dwRegType1, // 查詢資料的型別 lpRegDwordData, // 儲存所查詢的資料 &dwDataSize); // 預設定的資料長度 } catch(...) { return false; } if(lRet != ERROR_SUCCESS) { ::RegCloseKey(hKey); return false; } else { lpRegDwordData = new BYTE[dwDataSize]; try { lRet = ::RegQueryValueEx(hKey, lpRegValue, NULL, &dwRegType1, lpRegDwordData, &dwDataSize); } catch(...) { return false; } if(lRet != ERROR_SUCCESS) { delete []lpRegDwordData; ::RegCloseKey(hKey); return false; } } } DWORD num_HDD = DWORD(*lpRegDwordData); if (num_HDD==0) { return false; } char lpRegValue_HDD[16] = { 0 }; sprintf(lpRegValue_HDD, "%d", num_HDD-1); delete []lpRegDwordData; try { lRet = ::RegQueryValueEx(hKey, // 所開啟的鍵的控制代碼 lpRegValue_HDD, // 要查詢的鍵值名 NULL, &dwRegType2, // 查詢資料的型別 lpRegSzData, // 儲存所查詢的資料 &dwDataSize); // 預設定的資料長度 } catch(...) { return false; } if(lRet != ERROR_SUCCESS) { ::RegCloseKey(hKey); return false; } else { lpRegSzData = new BYTE[dwDataSize]; try { lRet = ::RegQueryValueEx(hKey, lpRegValue_HDD, NULL, &dwRegType2, lpRegSzData, &dwDataSize); } catch(...) { return false; } if(lRet != ERROR_SUCCESS) { delete []lpRegSzData; ::RegCloseKey(hKey); return false; } } ::RegCloseKey(hKey); memmove(GetUSBInfo->U_VID_PID, lpRegSzData+4, 17);//獲取VID_PID GetUSBInfo->U_VID_PID[17] = '\0'; char SN_temp[32]= {0}; memmove(SN_temp, lpRegSzData+22, 32); delete []lpRegSzData; char *needle="&"; char* buf = strstr( SN_temp, needle); if (buf != NULL) { //char *SN_1 = (char *)malloc(buf-SN_temp); char *temp = SN_temp; //buf[0]='\0'; //printf( "%s\n ", haystack); temp = buf + strlen(needle); /* Get next token: */ buf = strstr( temp, needle); if (buf != NULL) { int SN_strlen = buf - SN_temp; memmove(GetUSBInfo->U_SN, SN_temp, SN_strlen); GetUSBInfo->U_SN[SN_strlen] = '\0'; } else { memmove(GetUSBInfo->U_SN, SN_temp, 32); } } else { memmove(GetUSBInfo->U_SN, SN_temp, 32); }
上述方法對Windows XP、Windows 2000、Windows 7 32位和64位均有效。