繁体   English   中英

检查给定设备ID是否存在Windows驱动程序

[英]Check if a Windows driver exists for a given Device ID

我正在使用C ++编写Windows库。 该库应该能够检查系统上是否安装了特定设备的设备驱动程序。 所以我正在寻找一种方法来检查是否为已知的设备ID安装了驱动程序。

到目前为止,我发现了这个信息:

SetupDiBuildDriverInfoList列出给定设备的可用驱动程序。 但是,我必须提供的不仅仅是设备ID。

SetupDiGetClassDevs似乎完全返回我调用SetupDiBuildDriverInfoList所需的内容,但它仍然不会将设备ID作为输入。 它可能需要设备设置/接口类的GUID,但如果我理解正确,特定于供应商的驱动程序没有这样的GUID。 它也可能需要一个PnP枚举器,我不知道该告诉我是否可以以某种方式使用它。 或者最后,它可能需要设备实例ID - 但不是设备ID。

显然,我想检查任何相同类型的设备,因此通过设备实例ID查询是不可行的。 因此,问题是:如何使用我列出的API函数检查是否安装了给定设备ID的驱动程序(或任何其他可以识别设备的信息;我假设设备ID是正确的)或任何其他方式)?

您可以将设备ID转换为设备实例ID列表,如下所示:

#include <Windows.h>
#include <Cfgmgr32.h>
#include <SetupAPI.h>
#include <stdio.h>

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

int main(int argc, char ** argv)
{
    static wchar_t buffer[1024 * 1024];
    wchar_t * ptr;
    CONFIGRET result;

    result = CM_Get_Device_ID_ListW(L"usb\\vid_0461&pid_4d15", buffer,
               _countof(buffer), CM_GETIDLIST_FILTER_ENUMERATOR);

    if (result != CR_SUCCESS)
    {
        printf("CM_Get_Device_ID_ListW: %u\n", result);
        return 1;
    }

    ptr = buffer;

    while (*ptr)
    {
        printf("%ws\n", ptr);
        ptr += wcslen(ptr) + 1;
    }

    printf("Done\n");
    return 0;
}

或者像这样:

int main(int argc, char ** argv)
{
    HDEVINFO hdevinfo;

    SP_DEVINFO_DATA devinfo;
    wchar_t instance_id[4096];
    DWORD n;

    hdevinfo = SetupDiGetClassDevs(NULL, L"usb\\vid_0461&pid_4d15", 
                 NULL, DIGCF_ALLCLASSES);

    if (hdevinfo == INVALID_HANDLE_VALUE)
    {
        DWORD err = GetLastError();
        printf("SetupDiGetClassDevs: %u\n", err);
        return 1;
    }

    for (n = 0;; n++)
    {
        devinfo.cbSize = sizeof(devinfo);
        if (!SetupDiEnumDeviceInfo(hdevinfo, n, &devinfo))
        {
            DWORD err = GetLastError();
            printf("SetupDiEnumDeviceInfo: %u\n", err);
            break;
        }

        if (!SetupDiGetDeviceInstanceId(hdevinfo, &devinfo, 
               instance_id, _countof(instance_id), NULL))
        {
            DWORD err = GetLastError();
            printf("SetupDiGetDeviceInstanceId: %u\n", err);
        }
        else
        {
            printf("DevicePath: %ws\n", instance_id);
        }
    }

    return 0;
}

第一个代码示例使用较旧的API CM_Get_Device_ID_List

第二个代码示例使用较新的API SetupDiGetClassDevs ,但请注意,未记录使用设备ID而非仅使用枚举器的功能。 它有效,但没有记录。

在任何一种情况下,设备当前都不必存在,但必须在过去的某个时刻安装。

如果您不确定所需设备ID的格式是否正确,则可以列出所有设备实例。 设备ID只是设备实例ID,其中删除了特定于实例的ID ,即一切尽可能但不包括最后一个反斜杠。)

在第一个代码示例中,使用CM_GETIDLIST_FILTER_NONE获取所有设备实例的列表。

在第二个代码示例中,传递NULL而不是设备ID字符串以获取所有设备实例的列表。

哈利约翰斯顿的回答让我很接近,但我不得不多补充一点才能让它发挥作用。 缺少的神奇之处在于我必须在SetupDiEnumDriverInfoW实际执行一些有用的SetupDiBuildDriverInfoList之前调用SetupDiEnumDeviceInfoSetupDiBuildDriverInfoList

这是一个完整的(模数清理)示例,替换传递给SetupDiGetClassDevsW的字符串以匹配您自己的设备。 对于我的特定设备,它打印

Driver found: description: USBXpress Device, MfgName: Silicon Labs, ProviderName: Silicon Laboratories Inc.

在安装了驱动程序的PC上

No driver found

在没有安装驱动程序的PC(实际上是VM)上。

#include <Windows.h>
#include <SetupAPI.h>
#include <stdio.h>
#include <stdlib.h>

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

int main(int argc, char ** argv)
{
    HDEVINFO hdevinfo = SetupDiGetClassDevsW(NULL, LR"(USB\VID_10C4&PID_EA61)",
                                             NULL, DIGCF_ALLCLASSES);
    if (hdevinfo == INVALID_HANDLE_VALUE)
    {
        DWORD err = GetLastError();
        printf("SetupDiGetClassDevs: %u\n", err);
        return 1;
    }

    SP_DEVINFO_DATA devinfo;
    devinfo.cbSize = sizeof(devinfo);
    if (!SetupDiEnumDeviceInfo(hdevinfo, 0, &devinfo))
    {
        DWORD err = GetLastError();
        printf("SetupDiEnumDeviceInfo: %u %d\n", err, 0);
        return 1;
    }

    if (!SetupDiBuildDriverInfoList(hdevinfo, &devinfo, SPDIT_COMPATDRIVER)) {
        printf("error %d\n", GetLastError());
        return 1;
    }

    SP_DRVINFO_DATA_W drvdata;
    drvdata.cbSize = sizeof(SP_DRVINFO_DATA_W);
    BOOL worked = SetupDiEnumDriverInfoW(hdevinfo, &devinfo, SPDIT_COMPATDRIVER,
                                         0, &drvdata);
    if (worked) {
        printf("Driver found: description: %ws, MfgName: %ws, ProviderName: %ws\n",
               drvdata.Description, drvdata.MfgName, drvdata.ProviderName);
    }
    else {
        DWORD err = GetLastError();
        if (err == ERROR_NO_MORE_ITEMS)
            printf("No driver found\n");
        else {
            printf("SetupDiEnumDriverInfoW: %d", err);
            return 1;
        }
    }
    return 0;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM