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);
看起来我要找的东西是不可能的:
不支持计算您引用的id的方法以编程方式。这从来都不是一个设计目标应用程序用与屏幕相同的id标记监视器分辨率控制面板使用