首页 资讯 社群 我的社区 搜索

通过 setupapi 中的函数获取Windows 系统已安装设备的信息

木须虎
2020-07-05 10:47:35

还是最近的一需求,我们需要知道这台机器上已经安装了哪些设备,如:显卡、声卡、主板、USB 设备等,之前曾借助 aida64 (知名的硬件设备检测工具) 来扫描整机的硬件信息,这个工具非常强大,经常被用于识别硬件,对于一些未知设备或打磨贴牌的设备也能被它认出来,我们国常用的如驱动精灵、鲁大师等工具工具也有相类的功能,原理是枚举系统总线,将所有设备的硬件ID ( VEN & DEV ) 号读出,再从数据库中查询,硬件ID 有国际标准组织统一规范,不是厂商可以随意自己定义,而且这个信息已经写在设备的固件中,它是固定不变的即使没有安装操作系统,BIOS 中就已经可以读到所有设备的ID ,不会因为操作系统的不同而有差异,所以理论上这种方法是最专业最标准的。

但是我们目前条件有限有没有数据库的支撑,而且我们的需求也没有这么复杂,我们并不是要重构一个类似驱动精灵的东西,只是在项目中想了解当前这台终端安装了那些设备,这些从Windows 系统的 “设备管理器” 中已经一目了然。我们能和“设备管理器” 读到一样的信息即可。

当需求被简化后,很多问题就简单了,windows 的 SDK 中提供了 setupapi.h 当中就包含了我们所需要的函数。

MSDN 的官方文档:

https://docs.microsoft.com/zh-cn/windows/win32/api/setupapi/

这里包含了很多设备安装设备等相关的函数,废话不多,直接上代码:

// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <stdio.h>
#include <windows.h>
#include <setupapi.h>
#include <devguid.h>
#include <regstr.h>
#include <locale.h>

#pragma comment( lib,"setupapi.lib")

//https://docs.microsoft.com/zh-cn/windows/win32/api/setupapi/

int main(int argc, char* argv[], char* envp[])
{

	setlocale(LC_ALL, "");

	HDEVINFO hDevInfo;
	SP_DEVINFO_DATA DeviceInfoData;
	DWORD i;

	//https://docs.microsoft.com/zh-cn/windows/win32/api/setupapi/nf-setupapi-setupdigetclassdevsw?redirectedfrom=MSDN

	const GUID  ClassGuid[] = {   
		GUID_DEVCLASS_1394,
		GUID_DEVCLASS_1394DEBUG,
		GUID_DEVCLASS_61883,
		GUID_DEVCLASS_ADAPTER,
		GUID_DEVCLASS_APMSUPPORT,
		GUID_DEVCLASS_AVC,
		GUID_DEVCLASS_BATTERY,
		GUID_DEVCLASS_BIOMETRIC,
		GUID_DEVCLASS_BLUETOOTH,
		GUID_DEVCLASS_CDROM,
		GUID_DEVCLASS_COMPUTER,
		GUID_DEVCLASS_DECODER,
		GUID_DEVCLASS_DISKDRIVE,
		GUID_DEVCLASS_DISPLAY,
		GUID_DEVCLASS_DOT4,
		GUID_DEVCLASS_DOT4PRINT,
		GUID_DEVCLASS_ENUM1394,
		GUID_DEVCLASS_FDC,
		GUID_DEVCLASS_FLOPPYDISK,
		GUID_DEVCLASS_GPS,
		GUID_DEVCLASS_HDC,
		GUID_DEVCLASS_HIDCLASS,
		GUID_DEVCLASS_IMAGE,
		GUID_DEVCLASS_INFINIBAND,
		GUID_DEVCLASS_INFRARED,
		GUID_DEVCLASS_KEYBOARD,
		GUID_DEVCLASS_LEGACYDRIVER,
		GUID_DEVCLASS_MEDIA,
		GUID_DEVCLASS_MEDIUM_CHANGER,
		GUID_DEVCLASS_MEMORY,
		GUID_DEVCLASS_MODEM,
		GUID_DEVCLASS_MONITOR,
		GUID_DEVCLASS_MOUSE,
		GUID_DEVCLASS_MTD,
		GUID_DEVCLASS_MULTIFUNCTION,
		GUID_DEVCLASS_MULTIPORTSERIAL,
		GUID_DEVCLASS_NET,
		GUID_DEVCLASS_NETCLIENT,
		GUID_DEVCLASS_NETSERVICE,
		GUID_DEVCLASS_NETTRANS,
		GUID_DEVCLASS_NODRIVER,
		GUID_DEVCLASS_PCMCIA,
		GUID_DEVCLASS_PNPPRINTERS,
		GUID_DEVCLASS_PORTS,
		GUID_DEVCLASS_PRINTER,
		GUID_DEVCLASS_PRINTERUPGRADE,
		GUID_DEVCLASS_PROCESSOR,
		GUID_DEVCLASS_SBP2,
		GUID_DEVCLASS_SCSIADAPTER,
		GUID_DEVCLASS_SECURITYACCELERATOR,
		GUID_DEVCLASS_SENSOR,
		GUID_DEVCLASS_SIDESHOW,
		GUID_DEVCLASS_SMARTCARDREADER,
		GUID_DEVCLASS_SOUND,
		GUID_DEVCLASS_SYSTEM,
		GUID_DEVCLASS_TAPEDRIVE,
		GUID_DEVCLASS_UNKNOWN,
		GUID_DEVCLASS_USB,
		GUID_DEVCLASS_VOLUME,
		GUID_DEVCLASS_VOLUMESNAPSHOT,
		GUID_DEVCLASS_WCEUSBS,
		GUID_DEVCLASS_WPD,
		GUID_DEVCLASS_EHSTORAGESILO,
		GUID_DEVCLASS_FIRMWARE,
		GUID_DEVCLASS_EXTENSION
	};

	int guid_count = sizeof(ClassGuid) / sizeof(GUID);

	for ( int guid_i = 0 ; guid_i < guid_count ; guid_i++ )
	{
		hDevInfo = SetupDiGetClassDevs(
			&ClassGuid[guid_i],
			//NULL,
			NULL, // Enumerator
			NULL,
			DIGCF_PRESENT );
			//DIGCF_PRESENT | DIGCF_ALLCLASSES );


		if (hDevInfo == INVALID_HANDLE_VALUE)
		{
			return 1;
		}
		
		printf("============================= %x ========================================n", ClassGuid[guid_i]);

		// Enumerate through all devices in Set.
		DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);

		for (i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &DeviceInfoData); i++)
		{
			DWORD DataT;
			LPTSTR buffer = NULL;
			DWORD buffersize = 0;

			while (!SetupDiGetDeviceRegistryProperty(hDevInfo,
				&DeviceInfoData,
				SPDRP_DEVICEDESC,
				&DataT,
				(PBYTE)buffer,
				buffersize,
				&buffersize))
			{
				if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
				{
					if (buffer) LocalFree(buffer);
					buffer = (LPTSTR)LocalAlloc(LPTR, buffersize * 2);
				}
				else
				{
					break;
				}
			}

			printf("%lsn", buffer);

			if (buffer) LocalFree(buffer);
		}

		if (GetLastError() != NO_ERROR && GetLastError() != ERROR_NO_MORE_ITEMS)
		{
			return 1;
		}

		SetupDiDestroyDeviceInfoList(hDevInfo);
	}

	getchar();
	return 0;

}
用户评论