Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/319.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# SetupDiGetDeviceRegistrProperty失败,错误为\u无效\u数据_C#_Winapi_Interop - Fatal编程技术网

C# SetupDiGetDeviceRegistrProperty失败,错误为\u无效\u数据

C# 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

我正在尝试获取屏幕分辨率窗口Win8.1 x64中显示的名称

首先,我尝试了一些新设备

第二次调用EnumDisplayDevices with EDD_GET_DEVICE_INTERFACE_NAME确实生成了显示名称,正如它在display_DEVICEW.DeviceString中为我的主显示器显示的一样。但是,对于我的HDMI连接电视,该字段包含通用PnP显示器,而不是屏幕分辨率窗口中显示的三星显示器。也许它通过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失败,返回错误\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);