SetupDiGetDeviceRegistryProperty

SetupDiGetDeviceRegistryProperty

本文介绍了SetupDiGetDeviceRegistryProperty失败,错误码为ERROR_INVALID_DATA的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图获取显示名称,它们出现在屏幕分辨率"窗口中(Win8.1 x64).

I'm trying to get the display names as they appear in the "Screen Resolution" window (Win8.1 x64).

首先我尝试了EnumDisplayDevices

var deviceInfo = new DISPLAY_DEVICEW();
uint i = 0;
while (true)
{
    if (!NativeMethods.EnumDisplayDevices(null, i++, deviceInfo, 0))
    {
        break;
    }
    PrintDeviceInfo(deviceInfo);

    NativeMethods.EnumDisplayDevices(deviceInfo.DeviceName, 0, deviceInfo, EDD_GET_DEVICE_INTERFACE_NAME);
    PrintDeviceInfo(deviceInfo);
}

第二次调用EnumDisplayDevices(使用EDD_GET_DEVICE_INTERFACE_NAME)的确产生了显示名称,该名称显示在我的主显示器上(在DISPLAY_DEVICEW.DeviceString中).但是,对于我连接HDMI的电视,该字段包含通用PnP监视器" ,而不是屏幕分辨率"窗口中显示的 SAMSUNG .也许它通过HDMI连接的事实与某种方式有关?

The second call to EnumDisplayDevices (with EDD_GET_DEVICE_INTERFACE_NAME) indeed yielded the display name as it appears for my main display (in DISPLAY_DEVICEW.DeviceString). However for my HDMI-connected TV that field contains Generic PnP Monitor, instead of SAMSUNG as it appears in the "Screen Resolution" Window. Perhaps the fact that it's connected by HDMI is somehow related?

然后我尝试了Setup API

I then tried the Setup API

var hdevinfo = NativeMethods.SetupDiGetClassDevs(ref GUID_DEVINTERFACE_MONITOR, null, IntPtr.Zero, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
if (hdevinfo == INVALID_HANDLE_VALUE) return;
var spDeviceInterfaceData = new SP_DEVICE_INTERFACE_DATA();
uint memberIndex = 0;
while (true)
{
    bool success = NativeMethods.SetupDiEnumDeviceInterfaces(hdevinfo, null, ref GUID_DEVINTERFACE_MONITOR, memberIndex++, spDeviceInterfaceData);
    if (!success)
    {
        break;
    }
    PrintInterfaceData(spDeviceInterfaceData);

    uint requiredSize;
    var devInfoData = new SP_DEVINFO_DATA();

    NativeMethods.SetupDiGetDeviceInterfaceDetail(hdevinfo, spDeviceInterfaceData, IntPtr.Zero, 0, out requiredSize, devInfoData);
    PrintDevInfoData(devInfoData);

    var interfaceDetail = Marshal.AllocHGlobal((int)requiredSize);
    var cbSize = (Marshal.SizeOf(typeof(uint)) + Marshal.SystemDefaultCharSize);
    Marshal.WriteInt32(interfaceDetail, 0, cbSize);
    NativeMethods.SetupDiGetDeviceInterfaceDetail(hdevinfo, spDeviceInterfaceData, interfaceDetail, requiredSize, IntPtr.Zero, null);
    var dynamicType = GetDeviceInterfaceDetailDataType(requiredSize);
    var interfaceDetailStruct = Marshal.PtrToStructure(interfaceDetail, dynamicType);
    Marshal.FreeHGlobal(interfaceDetail);
    PrintInterfaceDetail(interfaceDetailStruct);

    uint propertyRegDataType;
    NativeMethods.SetupDiGetDeviceRegistryProperty(hdevinfo, devInfoData, SPDRP_FRIENDLYNAME, out propertyRegDataType, null, 0, out requiredSize);
    Console.WriteLine(Marshal.GetLastWin32Error());
}

查看从不同方法返回的值,一切似乎都可以正常工作,但是对SetupDiGetDeviceRegistryProperty的最后一次调用因ERROR_INVALID_DATA而失败(也就是说,该方法返回false,而GetLastWin32Error产生13).根据 docs ,这表示设备不存在请求的属性,或者属性数据无效.

Looking at the returned values from the different methods, everything seems to work, but the last call to SetupDiGetDeviceRegistryProperty fails with ERROR_INVALID_DATA (that is, the method returns false and GetLastWin32Error yields 13). According to the docs, this means that the requested property does not exist for a device or if the property data is not valid.

我实际上遍历了所有可能的SPDRP值(0-24),它们都导致相同的失败.为了明确起见,我希望该方法会失败,但是要设置ERROR_INSUFFICIENT_BUFFER并设置requiredSize(由于非托管代码不会更改它,后者只是保留了它以前的值).

I actually looped over all possible SPDRP values (0-24) and they all result in the same failure. Just to clarify, I expected the method to fail, but with ERROR_INSUFFICIENT_BUFFER and having requiredSize set (the latter simply retains its previous value, as the unmanaged code doesn't change it).

这是SetupDiGetDeviceRegistryProperty的签名(所有其他方法均按预期工作):

Here's the signature for SetupDiGetDeviceRegistryProperty (all other methods work as expected):

[StructLayout(LayoutKind.Sequential)]
public class SP_DEVINFO_DATA
{
    public uint cbSize = (uint) Marshal.SizeOf(typeof (SP_DEVINFO_DATA));
    public Guid ClassGuid;
    public uint DevInst;
    public IntPtr Reserved;
}
[DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool SetupDiGetDeviceRegistryProperty(
    IntPtr deviceInfoSet,
    SP_DEVINFO_DATA deviceInfoData,
    uint property,
    out uint propertyRegDataType,
    byte[] propertyBuffer,
    uint propertyBufferSize,
    out uint requiredSize);

推荐答案

我正在寻找的是不可能:

这篇关于SetupDiGetDeviceRegistryProperty失败,错误码为ERROR_INVALID_DATA的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-14 12:27