C# SetupDiGetDeviceRegistrProperty失败,错误为\u无效\u数据
我正在尝试获取屏幕分辨率窗口Win8.1 x64中显示的名称 首先,我尝试了一些新设备 第二次调用EnumDisplayDevices with EDD_GET_DEVICE_INTERFACE_NAME确实生成了显示名称,正如它在display_DEVICEW.DeviceString中为我的主显示器显示的一样。但是,对于我的HDMI连接电视,该字段包含通用PnP显示器,而不是屏幕分辨率窗口中显示的三星显示器。也许它通过HDMI连接的事实有某种关联 然后我尝试了安装APIC# SetupDiGetDeviceRegistrProperty失败,错误为\u无效\u数据,c#,winapi,interop,C#,Winapi,Interop,我正在尝试获取屏幕分辨率窗口Win8.1 x64中显示的名称 首先,我尝试了一些新设备 第二次调用EnumDisplayDevices with EDD_GET_DEVICE_INTERFACE_NAME确实生成了显示名称,正如它在display_DEVICEW.DeviceString中为我的主显示器显示的一样。但是,对于我的HDMI连接电视,该字段包含通用PnP显示器,而不是屏幕分辨率窗口中显示的三星显示器。也许它通过HDMI连接的事实有某种关联 然后我尝试了安装API var hdevin
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失败,返回错误\u无效\u数据,即该方法返回false,GetLastWin32Error返回13。根据,这意味着设备不存在请求的属性,或者属性数据无效
我实际上循环了所有可能的SPDRP值0-24,它们都会导致相同的失败。我只是想澄清一下,我预计该方法会失败,但由于错误缓冲区不足,并且设置了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标记监视器 分辨率控制面板使用
为什么要忽略所有的返回值?您尝试过用C++来做这件事吗?在这里,Windows API提供了具有正确定义的头文件,而不需要自己编写文件。在设备节点上也可以有多个设备接口。我并没有忽略返回值,只是为了简洁起见省略了它们。在我的实际测试程序中,我打印了所有返回值、Win32错误和返回的值/结构。我看不出您实际在哪里使用EnumDisplayDevices的结果。哦,我想我明白了,您是指memberIndex参数。接得好,我来试一试。
[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);