通过Windows注册表获取U盘、移动硬盘和USB读卡器等设备的PID、VID和序列号

    当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、...表项的键值就记录这响应设备的信息,这个序号是根据设备插入系统的先后顺序递增记录的,具体如下图:

通过Windows注册表获取U盘、移动硬盘和USB读卡器等设备的PID、VID和序列号_第1张图片

通过编程代码可以访问该数据项,进行解析即可,一般当前插入的设备应该排在序号的最后一位。具体流程如下,代码测试环境为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位均有效。

你可能感兴趣的:(usb,注册表,PID,VID,序列号,其他技术方向)