我如何从c++获得Windows上的驱动程序版本?

How do I get the version of a driver on Windows from C++

本文关键字:驱动程序 版本 Windows 获得 c++      更新时间:2023-10-16

我正在寻找一种编程方式来获取驱动程序的版本号。我想要与设备管理器在设备的驱动程序属性中显示的数字相同。

背景:我有一个与一些自定义硬件对话的应用程序。自定义硬件的设备驱动程序在某个版本号之前有已知的错误。我希望应用程序检查驱动程序版本并警告用户,如果他们需要更新它。该应用程序运行在Windows XP和Windows 7上,使用c++编写。

我以前使用的一个hack是直接从system32/drivers读取。sys文件,并直接搜索"FileVersion"。这是不好的,原因有很多。特别是在Windows 7上,它似乎需要管理员权限。

我知道类GUID和硬件ID(即"USBVID_1234&PID_5678")。

应用程序目前使用SetupDiGetClassDevs, SetupDiEnumDeviceInterfaces和SetupDiGetDeviceInterfaceDetail来获取"DevicePath"。然后使用该路径调用CreateFile来与驱动程序对话。

看起来我需要从某个地方获得SP_DRVINFO_DATA结构。我尝试了setupapi.h中的各种功能,例如SetupDiGetDeviceInterfaceDetail。以下是我尝试过的一些失败的代码:

int main(void)
{
    HDEVINFO DeviceInfoSet = SetupDiGetClassDevs((LPGUID)&GUID_DEVINTERFACE_USBSPI, NULL, NULL,
        DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
    SP_INTERFACE_DEVICE_DATA InterfaceDeviceData;
    InterfaceDeviceData.cbSize = sizeof(SP_INTERFACE_DEVICE_DATA);
    // Cycle through all devices.
    for (int i = 0; i < 32; i++)
    {
        if (!SetupDiEnumDeviceInterfaces(DeviceInfoSet, 0, (LPGUID)&GUID_DEVINTERFACE_USBSPI, i, &InterfaceDeviceData))
            break;
        PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData;
        DWORD RequiredSize;
        SetupDiGetDeviceInterfaceDetail(DeviceInfoSet, &InterfaceDeviceData, NULL, 0, &RequiredSize, NULL);
        DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS | HEAP_ZERO_MEMORY, RequiredSize); 
        try
        {
            DeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
            SetupDiGetDeviceInterfaceDetail(DeviceInfoSet, &InterfaceDeviceData, DeviceInterfaceDetailData, RequiredSize, NULL, NULL);
            // Try to get the driver info. This part always fails with code 
            // 259 (ERROR_NO_MORE_ITEMS).
            SP_DRVINFO_DATA drvInfo;
            drvInfo.cbSize = sizeof(SP_DRVINFO_DATA);
            if (!SetupDiEnumDriverInfo(DeviceInfoSet, NULL, SPDIT_CLASSDRIVER, i, &drvInfo))
                printf("error = %dn", GetLastError());
            printf("Driver version is %08x %08xn", drvInfo.DriverVersion >> 32, drvInfo.DriverVersion & 0xffffffff);
        }
        catch(...)
        {
            HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailData);
            throw;
        }
        HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailData);
    }
    SetupDiDestroyDeviceInfoList(DeviceInfoSet);
    return 0;
}

编辑 -我更新的代码现在看起来像这样:

HDEVINFO devInfoSet = SetupDiGetClassDevs(&GUID_DEVINTERFACE_USBSPI, NULL, NULL,
                                          DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
// Cycle through all devices.
for (int i = 0; ; i++)
{
    // Get the device info for this device
    SP_DEVINFO_DATA devInfo;
    devInfo.cbSize = sizeof(SP_DEVINFO_DATA);
    if (!SetupDiEnumDeviceInfo(devInfoSet, i, &devInfo))
        break;
    // Get the first info item for this driver
    SP_DRVINFO_DATA drvInfo;
    drvInfo.cbSize = sizeof(SP_DRVINFO_DATA);
    if (!SetupDiEnumDriverInfo(devInfoSet, &devInfo, SPDIT_COMPATDRIVER, 0, &drvInfo))
        printf("err - %dn", GetLastError()); // Still fails with "no more items"
}
SetupDiDestroyDeviceInfoList(devInfoSet);

您错误地重用i作为SetupDiEnumDriverInfo的索引。这应该是每个驱动程序的每个驱动程序信息元素的内部循环。因此,您无法检索设备#1的驱动程序信息#0。

但是,这并不能解释为什么设备#0的信息#0失败了。为此,你必须看SetupDiEnumDriverInfo的第二个参数。这是您的设备的SP_DEVINFO_DATA结构,但您将其设置为NULL。那让你获得与设备类关联的驱动程序列表,而不是设备。也就是说,这适用于鼠标和USB棒,它们有类驱动程序。您的设备可能有特定于供应商的驱动程序,因此您需要该特定设备的驱动程序。

你问了一个几乎相同的问题,我只在这里贴出我的答案的链接:

为什么SetupDiEnumDriverInfo给出我的驱动程序的两个版本号