SetupDiGetDeviceRegistryProperty失败,返回ERROR_INVALID_DATA

本文关键字:INVALID DATA ERROR 返回 失败 SetupDiGetDeviceRegistryProperty | 更新日期: 2023-09-27 18:10:02

我试图获得显示名称,因为它们出现在"屏幕分辨率"窗口(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连接的事实在某种程度上是相关的?

然后尝试安装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)。根据文档,这意味着设备不存在请求的属性,或者如果属性数据无效

我实际上遍历了所有可能的SPDRP值(0-24),它们都导致相同的失败。只是为了澄清,我预计该方法会失败,但使用ERROR_INSUFFICIENT_BUFFER并设置requiredSize(后者只是保留其先前的值,因为非托管代码不会更改它)。

以下是SetupDiGetDeviceRegistryProperty的签名(所有其他方法都按预期工作):

[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

看起来我要找的东西是不可能的:

不支持计算您引用的id的方法以编程方式。这从来都不是一个设计目标应用程序用与屏幕相同的id标记监视器分辨率控制面板使用

相关文章: