Windows 驱动器号到设备实例ID
如何从驱动器号获取设备实例ID 我的流程从设备到达消息开始。我已成功地从到达信息中获取驱动器盘符并打开dvd托盘 我搜索了各种设置API项;但我还没有找到任何可以将驱动器号转换为设备实例ID的东西 C#或VB.NET中的解决方案是理想的,但我愿意从任何其他语言中找到它,只要我能看到API调用Windows 驱动器号到设备实例ID,windows,device,hardware-interface,device-instance-id,Windows,Device,Hardware Interface,Device Instance Id,如何从驱动器号获取设备实例ID 我的流程从设备到达消息开始。我已成功地从到达信息中获取驱动器盘符并打开dvd托盘 我搜索了各种设置API项;但我还没有找到任何可以将驱动器号转换为设备实例ID的东西 C#或VB.NET中的解决方案是理想的,但我愿意从任何其他语言中找到它,只要我能看到API调用 提前感谢…您不能直接完成 链接是使用存储设备\u编号。您可以使用设备名上带有IOCTL\u STORAGE\u GET\u DEVICE\u NUMBER的DeviceIoControl来填充此结构。将此值
提前感谢…您不能直接完成 链接是使用
存储设备\u编号
。您可以使用设备名上带有IOCTL\u STORAGE\u GET\u DEVICE\u NUMBER
的DeviceIoControl来填充此结构。将此值放在一边。然后,您需要使用
SetupDiGetClassDevs
将guid设置为适当的,指示安装的驱动器,以获取系统上的设备信息。然后使用SetupDiEnumDeviceInfo
枚举设备。然后使用SetupDiEnumDeviceInterfaces
枚举接口,最后使用SetupDiGetDeviceInterfaceDetail
获取信息。在返回的这个结构中,您可以获得一个DevicePath,您可以使用它来获取如上所述的存储设备编号。将其与驱动器号中的存储设备号
相匹配,您现在已将驱动器号链接到您的结构。呸!在这个结构里面是一个魔鬼。我知道现在对你来说已经晚了,但对每个人来说都不是^^
我也有同样的需求,这是我如何做到这一点的主线:
-您需要一个窗口来接收设备到达和移除(如您所说)
-然后创建一个DeviceNotificationFilter,该过滤器被初始化为dbcc_devicetype=DBT_DEVTYP_DEVICEINTERFACE
-然后在窗口的消息循环中查找VM_DEVICECHANGE
-如果wParam==DBT_DEVICEARRIVAL,当您收到它时,请使用LPRAM检查它是DBT_DEVTYPE_卷(我在这里得到的是盘符和驱动器类型)还是DBT_DEVTYPE_DEVICEINTERFACE(在这里您可以使用良好的LPRAM从输入结构中获取InstanceId)
当您连接驱动器时,首先是接收设备接口,然后是另一个。
我只给出了主线,因为我很久以前就这么做了,我这里没有代码,而且我在网上发现了很多代码片段(很久以前,所以现在应该有更多的代码片段)^^^^也许msdn现在给出了一个完整的代码示例
如果你读了这篇文章,需要更多的信息,我会回复,如果很多人需要的话,我会做一个完整的书面回答
希望它能对你们中的一些人有所帮助。我知道这是多年以后的事了,但我不得不这么做,搜索把我带到了这里,@DanDan的答案奏效了。为了给未来的人们节省大量的工作,我想我应该回馈一点,并更明确地介绍这项技术。您仍然需要编写一些代码,但我发现困难的部分如下:
正如DanDan提到的,其想法是使用CreateFile
和DeviceIoControl
获取与文件路径相关联的磁盘的WindowsSTORAGE\u DEVICE\u NUMBER
,然后使用Setup API枚举磁盘设备,直到找到一个设备实例等于SDN为止
首先,这里是如何从路径(例如c:\\users\\bob
)获取存储设备编号的摘要
剥离到根目录的路径(例如,向下到C:
)并在其前面加上\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\C:
使用CreateFileW
打开该路径以获取元数据
将DeviceIoControl
与IOCTL\u VOLUME\u GET\u VOLUME\u DISK\u区段一起使用以获取区段
从返回的第一个扩展数据块中获取DiskNumber
成员
关闭文件
打开\\.\\PhysicalDrive
,其中
是第一个区段的磁盘号
将DeviceIoControl
与codeIOCTL\u STORAGE\u GET\u DEVICE\u NUMBER
一起使用,使其填写STORAGE\u DEVICE\u NUMBER
结构作为输出
使用带有参数的SetupDiGetClassDevs
和磁盘驱动器和DICGF\u PRESENT
获取系统上的所有磁盘
在循环中,使用SetupDiEnumDeviceInfo
反复(在上面步骤8返回的设备列表上)获取SP_设备信息数据
,并调用下面的函数,以确定哪一个(如果有)与给定路径的存储设备编号
匹配
(这是为了删除SO网页上我的自定义实用程序类而编辑的,因此我可能引入了错误/打字错误)
bool DOESDEVICEINSTACEQUALS存储设备编号(
常量标准::字符串和偏差,
存储设备编号(sdn)
{
//打开此设备实例,指定需要*接口*。
//接口是关键,因为检查它们会让我们得到一个
//字符串我们可以使用Win32 CreateFile函数。
const auto hDevInfo=SetupDiGetClassDevsA(
nullptr,
devInstance.c_str(),
nullptr,
DIGCF_设备接口| DIGCF_所有类);
if(hDevInfo==无效的句柄值)
抛出std::runtime_错误(“无法获取磁盘设备”);
DWORD dwSize=0;
SP_DEVINFO_数据不存在;
WCHAR缓冲区[4096];
did.cbSize=sizeof(did);
bool foundValidMatch=false;
int deviceNumber=0;
//遍历所有此类设备,查找存储设备号与给定设备号匹配的设备。
而(!foundValidMatch&&SetupDiEnumDeviceInfo(hDevInfo、deviceNumber和did))
{
deviceNumber++;
DEVPROPTYPE DEVPROPTYPE;
//我们只会比较这一个,如果它是固定的。确定它。
const auto getPropResult=SetupDiGetDevicePropertyW(
hDevI
bool DoesDeviceInstanceEqualStorageDeviceNumber(
const std::string& devInstance,
STORAGE_DEVICE_NUMBER sdn)
{
// Open up this device instance, specifying that we want the *interfaces*.
// The interfaces are key key because examining them will let us get a
// string we can use the Win32 CreateFile function.
const auto hDevInfo = SetupDiGetClassDevsA(
nullptr,
devInstance.c_str(),
nullptr,
DIGCF_DEVICEINTERFACE | DIGCF_ALLCLASSES);
if (hDevInfo == INVALID_HANDLE_VALUE)
throws std::runtime_error("Unable to get disk devices");
DWORD dwSize = 0;
SP_DEVINFO_DATA did;
WCHAR buffer[4096];
did.cbSize = sizeof (did);
bool foundValidMatch = false;
int deviceNumber = 0;
// Iterate through all such devices, looking for one that has a storage device number that matches the given one.
while ( !foundValidMatch && SetupDiEnumDeviceInfo(hDevInfo, deviceNumber, &did))
{
deviceNumber++;
DEVPROPTYPE devPropType;
// We'll only bother comparing this one if it is fixed. Determine that.
const auto getPropResult = SetupDiGetDevicePropertyW (
hDevInfo,
&did,
&DEVPKEY_Device_RemovalPolicy, // Ask for the "removal policy"
&devPropType,
(BYTE*)buffer,
sizeof(buffer),
&dwSize,
0);
if (!getPropResult)
{
std::cerr << "Unable to to get removal policy for disk device: " << ::GetLastError() << std::endl;
continue;
}
/* This bit *would* skip removable disks, you wanted...
else if (buffer[0] != 1)
{
std::cerr << "Skipping removable disk device " << devInstance << std::endl;
continue;
}
*/
// OK this is a fixed disk so it might be the one we'll compare against
// 1. Get the very first disk interface from this particular disk device
// 2. Open a file on it
// 3. Query the resulting file for its device number.
// 4. Compare the device number to the one we determined above
// 5. If it matches ours, then we succeed. If not, continue
SP_DEVICE_INTERFACE_DATA devIntData;
devIntData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
// Get the disk interfaces
const auto result = SetupDiEnumDeviceInterfaces(
hDevInfo,
&did, //&did,
&GUID_DEVINTERFACE_DISK, // Get Disk Device Interface (from winioctl.h)
0, // We only need the very FIRST one. I think...
&devIntData);
if (!result)
continue;
DWORD dwRequiredSize = 0;
// Want to get the detail but don't yet know how much space we'll need
// Do a dummy call to find out
SetupDiGetDeviceInterfaceDetail(
hDevInfo,
&devIntData,
nullptr,
0,
&dwRequiredSize,
nullptr);
if (ERROR_INSUFFICIENT_BUFFER != ::GetLastError())
{
std::cerr << "Unable to get device interface Detail: " << ::GetLastError() << std::endl;;
}
else
{
// Get the detail data so we can get the device path and open a file.
std::vector<TCHAR> buf(dwRequiredSize);
auto pDidd = reinterpret_cast<PSP_DEVICE_INTERFACE_DETAIL_DATA>(buf.data());
// WARNING: HARD CODED HACK
// ------------------------
// https://stackoverflow.com/questions/10405193/vb-net-hid-setupdigetdeviceinterfacedetail-getlasterror-shows-1784-error-inv
//
// Don't ask. Just do what they tell you.
// -----------------------------------------------------------------
#ifdef BUILD_64
pDidd->cbSize = 8;
#else
pDidd->cbSize = 6;
#endif
// -----------------------------------------------------------------
if (!SetupDiGetDeviceInterfaceDetail(
hDevInfo,
&devIntData,
pDidd,
dwRequiredSize,
&dwRequiredSize,
nullptr))
{
std::cerr << "Cannot get interface detail: " << ::GetLastError());
}
else
{
// FINALLY: We now have a DevicePath that we can use to open up
// in a Win32 CreateFile() call. That will let us get the
// STORAGE_DEVICE_NUMBER and compare it to the one we were given.
const auto hFile = ::CreateFileW(pDidd->DevicePath, 0, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, NULL);
if (INVALID_HANDLE_VALUE != hFile)
{
std::cerr << "Unable to open logical volume: " + devicePath << std::endl;
continue;
}
STORAGE_DEVICE_NUMBER sdnTest;
ZeroMemory(&sdnTest, sizeof(STORAGE_DEVICE_NUMBER));
if (0 == DeviceIoControl(
hDevInfo
IOCTL_STORAGE_GET_DEVICE_NUMBER,
nullptr, // output only so not needed
0, // output only so not needed
&sdnTest,
sizeof(STORAGE_DEVICE_NUMBER),
nullptr,
nullptr))
{
std::cerr << "Unable to determine storage device number: " << ::GetLastError() << std::endl;);
}
else
{
// All this for a one-line test...
foundValidMatch = sdnTest.DeviceNumber == sdn.DeviceNumber;
}
}
}
}
SetupDiDestroyDeviceInfoList(hDevInfo);
return foundValidMatch;
}