Windows 驱动器号到设备实例ID

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来填充此结构。将此值

如何从驱动器号获取设备实例ID

我的流程从设备到达消息开始。我已成功地从到达信息中获取驱动器盘符并打开dvd托盘

我搜索了各种设置API项;但我还没有找到任何可以将驱动器号转换为设备实例ID的东西

C#或VB.NET中的解决方案是理想的,但我愿意从任何其他语言中找到它,只要我能看到API调用


提前感谢…

您不能直接完成

链接是使用
存储设备\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
获取与文件路径相关联的磁盘的Windows
STORAGE\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
    与code
    IOCTL\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;
    }