我正在使用C ++编写Windows库。该库应该能够检查系统上是否安装了特定设备的设备驱动程序。所以我正在寻找一种方法来检查是否为已知的Device ID安装了驱动程序。
到目前为止,我发现了这些信息:
SetupDiBuildDriverInfoList列出了给定设备的可用驱动程序。但是,我必须提供的不仅仅是设备ID。
SetupDiGetClassDevs似乎完全返回我调用SetupDiBuildDriverInfoList所需的内容,但它仍然不会将设备ID作为输入。它可能需要设备设置/接口类的GUID,但如果我理解正确,特定于供应商的驱动程序没有这样的GUID。它也可能需要一个PnP枚举器,我不知道该告诉我是否可以以某种方式使用它。或者最后,它可能需要Device Instance ID - 但不是设备ID。
显然,我想检查任何类型的设备,因此按设备实例ID查询是不可行的。因此,问题是:如何使用我列出的API函数检查是否安装了给定设备ID的驱动程序(或任何其他可以识别设备的信息;我假设设备ID是正确的)或任何其他方式)?
答案 0 :(得分:3)
您可以将设备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的格式是否正确,则可以列出所有设备实例。 (The device ID is just the device instance ID with the instance-specific ID removed,即一切,但不包括最后一个反斜杠。)
在第一个代码示例中,使用CM_GETIDLIST_FILTER_NONE
获取所有设备实例的列表。
在第二个代码示例中,传递NULL而不是设备ID字符串以获取所有设备实例的列表。
答案 1 :(得分:1)
哈里·约翰斯顿(Harry Johnston)的回答使我很接近,但是我不得不添加一些内容才能使它起作用。遗失的神奇之处在于,我必须先叫SetupDiEnumDeviceInfo
和SetupDiBuildDriverInfoList
才能真正发挥作用。
这是一个完整的(模清除)示例,请替换传递给SetupDiEnumDriverInfoW
的字符串以匹配您自己的设备。对于我的特定设备,它会打印
SetupDiGetClassDevsW
在已安装驱动程序的PC上
Driver found: description: USBXpress Device, MfgName: Silicon Labs, ProviderName: Silicon Laboratories Inc.
在未安装驱动程序的PC(实际上是VM)上。
No driver found