1

EnumDisplayDevices 的 MSDN 文档指出,将 NULL 作为第一个参数传递给函数会返回有关机器上显示适配器的信息(传递字符串会返回有关具有该名称的设备的信息)。

我在网上看到的各种 C# 示例将 null 传递给函数,如下所示:

result = EnumDisplayDevices(null, devNum, ref dd, flags);

但是,当我将 null 作为第一个参数传递时,我得到一个 System.AccessViolationException 并显示消息“尝试读取或写入受保护的内存”。

如果我将 null 更改为任何随机的非 null 字符串(例如,“hello”),则函数调用成功(我只是没有得到任何设备信息,因为没有名为“hello”的设备)。

那么如何将 null 作为第一个参数传递给 EnumDisplayDevices 函数呢?(我需要能够在随后的函数调用中传递名称)

我的代码的相关片段如下:

    [DllImport("user32.dll")]
    static extern bool EnumDisplayDevices(
        string lpDevice,
        uint iDevNum,
        ref DISPLAY_DEVICE lpDisplayDevice,
        uint dwFlags
        );

    [StructLayout(LayoutKind.Sequential)]
    public struct DISPLAY_DEVICE
    {
        public int cb;
        public string DeviceName;
        public string DeviceString;
        public int StateFlags;
        public string DeviceID;
        public string DeviceKey;
    }

    #region Public Interface
    public ObservableCollection<DisplayDevice> LoadDisplayDevices()
    {
        ObservableCollection<DisplayDevice> displayDevices = new ObservableCollection<DisplayDevice>();

        uint devNum = 0;
        uint flags = 0;
        bool result = false;

        DISPLAY_DEVICE dd = new DISPLAY_DEVICE();
        dd.cb = (int)Marshal.SizeOf(dd);

        try
        {
            result = EnumDisplayDevices(null, devNum, ref dd, flags);

            ...
4

1 回答 1

2

来自MSDN的原始定义:

typedef struct _DISPLAY_DEVICE {
  DWORD cb;
  TCHAR DeviceName[32];
  TCHAR DeviceString[128];
  DWORD StateFlags;
  TCHAR DeviceID[128];
  TCHAR DeviceKey[128];
} DISPLAY_DEVICE, *PDISPLAY_DEVICE;

所有字符串字段都定义为固定大小的数组。您的DISPLAY_DEVICE结构定义包含多个string值,但没有说明如何编组它们,因此它们将作为指针传递。您需要使用MarshalAsAttribute来解决此问题:

[StructLayout(LayoutKind.Sequential)]
public struct DISPLAY_DEVICE
{
    public int cb;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
    public string DeviceName;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
    public string DeviceString;
    public int StateFlags;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
    public string DeviceID;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
    public string DeviceKey;
}
于 2015-03-16T04:02:29.740 回答