[英]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
之前调用SetupDiEnumDeviceInfo
和SetupDiBuildDriverInfoList
。
这是一个完整的(模数清理)示例,替换传递给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.