MFC-SetupDiGetDeviceInstanceId获取设备的实例ID字符串

发布时间 2023-09-17 03:24:26作者: 天子骄龙

 

void show_instanceid_media() {

    // GUID_DEVCLASS_MEDIA
    HDEVINFO dev_info = SetupDiGetClassDevs(NULL, 0, 0, DIGCF_ALLCLASSES | DIGCF_PRESENT);//查询与指定参数匹配的所有已安装设备
    /*
    参数1:const GUID *ClassGuid  指向设备安装类或设备接口类的 GUID 的指针
                如果设定了标志(参数Flags的值)为DIGCF_ALLCLASSES,则这个参数可以忽略(NULL),且列表结果中包括所有已经安装的设备类别
    参数2:PCSTR Enumerator   提供包含设备实例的枚举注册表分支下的键名,可以通过它获取设备信息。
                    如果这个参数没有指定,则要从整个枚举树中获取所有设备实例的设备信息
    参数3:HWND hwndParent  提供顶级窗口的句柄,所有用户接口可以使用它来与成员联系,此句柄是可选的,可以为 NULL
    参数4:DWORD Flags   提供在设备信息结构中使用的控制选项。可以是以下数值:
            DIGCF_PRESENT - 只返回当前存在的设备。
            DIGCF_ALLCLASSES - 返回所有已安装的设备。如果这个标志设置了,ClassGuid参数将被忽略
            DIGCF_PROFILE - 只返回当前硬件配置文件中的设备
            DIGCF_INTERFACEDEVICE - 返回所有支持的设备。
            DIGCF_DEFAULT - 只返回与系统默认设备相关的设备
    返回值:HDEVINFO  如果函数运行成功,返回设备信息结构的句柄,该结构包含与指定参数匹配的所有已安装设备
            如果失败,则返回INVALID_HANDLE_VALUE。调用GetLastError可以获得更多错误信息
            HDEVINFO是个PVOID无类型指针
    需要:#include "setupapi.h"
            #pragma comment( lib, "setupapi.lib" )
    */

    CString str;

    for (int i = 0;; i++) {
        SP_DEVINFO_DATA dev_data{ 0 };
        /*
        SP_DEVINFO_DATA 结构体:它包含有关设备信息的数据
        typedef struct _SP_DEVINFO_DATA {
        DWORD         cbSize;  //结构体的大小(以字节为单位)。在调用函数之前,应将其设置为 sizeof(SP_DEVINFO_DATA)
        GUID          ClassGuid; //设备的类别 GUID
        DWORD         DevInst;   //设备实例句柄。它是设备管理器中设备的唯一标识符
        ULONG_PTR     Reserved;  //保留字段,应设置为 0
        } SP_DEVINFO_DATA, *PSP_DEVINFO_DATA;
        */
        dev_data.cbSize = sizeof(SP_DEVINFO_DATA);

        BOOL b = SetupDiEnumDeviceInfo(dev_info, i, &dev_data);
        /*
        用于枚举设备信息
        参数1:HDEVINFO DeviceInfoSet  设备信息集合的句柄。您可以通过使用 SetupDiGetClassDevs 或其他 SetupAPI 函数来创建此句柄

        参数2:DWORD MemberIndex  要枚举的设备的索引。从 0 开始,逐渐递增

        参数3:PSP_DEVINFO_DATA DeviceInfoData  指向 SP_DEVINFO_DATA 结构体的指针,用于接收设备信息

        返回值:如果函数成功执行,则返回非零值;
                如果函数失败,则返回零。如果需要获取更多错误信息,可以调用 GetLastError 函数

        */

        if (!b){ break; }
            
        TCHAR instance_id[256]={ 0 };
        DWORD require_size = 0;
        SetupDiGetDeviceInstanceId(dev_info, &dev_data, instance_id, sizeof(instance_id), &require_size);//获取设备的实例 ID
        /*
        参数1:HDEVINFO DeviceInfoSet 设备信息集合的句柄

        参数2:PSP_DEVINFO_DATA  DeviceInfoData 指向 SP_DEVINFO_DATA 结构体的指针,指定要获取实例 ID 的设备

        参数3:PTSTR DeviceInstanceId  指向字符数组的指针,用于接收设备的实例 ID 字符串

        参数4:DWORD DeviceInstanceIdSize   指定字符数组的大小,即 DeviceInstanceId 的容量(以字符数为单位)
         
        参数5:PDWORD RequiredSize  如果 DeviceInstanceId 缓冲区的大小不足以容纳实例 ID 字符串,则该参数将接收所需的大小(以字符数为单位),包括结尾的空字符

        返回值:如果成功,函数将返回 TRUE 。 
                否则,它将返回 FALSE ,并且可以通过调用 GetLastError 来检索记录的错误
        
        */

        str.Format(_T("%s\n"), instance_id);
        ::OutputDebugString(str);
        //注意这里获取的是只是设备实例标志符,如果想获取设备的更多信息需要去注册表获取
        //计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\
        //下面以PCI信息为例,获取硬件id
        
        //Registry::Read(HKEY_LOCAL_MACHINE, (CString("SYSTEM\\CurrentControlSet\\Enum\\") + instance_id).c_str(), "HardwareID", strHardWareID);
        //改成MFC的

    }
    SetupDiDestroyDeviceInfoList(dev_info);//销毁设备信息列表
}

void CsebaiDlg::OnBnClickedButton1()
{
    // TODO: 在此添加控件通知处理程序代码

    show_instanceid_media();

}