PInvoke的CreateDesktop(PInvoke CreateDesktop)

2019-10-17 14:31发布

我想的PInvoke CreateDesktop在传递标志继承由子进程桌面的方式。 声明如下:

[DllImport("user32", EntryPoint = "CreateDesktopW", CharSet = CharSet.Unicode, SetLastError = true)]
        public static extern IntPtr CreateDesktop(string lpszDesktop, IntPtr lpszDevice, IntPtr pDevmode, int dwFlags,
                                                  int dwDesiredAccess, [MarshalAs(UnmanagedType.LPStruct)] SECURITY_ATTRIBUTES lpsa);

        [StructLayout(LayoutKind.Sequential)]
        public struct SECURITY_ATTRIBUTES
        {
            public int nLength;
            public IntPtr lpSecurityDescriptor;
            public int bInheritHandle;
        }

我用它,如下所示:

Win32.SECURITY_ATTRIBUTES sa = new Win32.SECURITY_ATTRIBUTES();
            sa.nLength = Marshal.SizeOf(sa);
            sa.bInheritHandle = 1;
            testDesktopHandle = Win32.CreateDesktop(name, IntPtr.Zero, IntPtr.Zero, 0, Win32.GENERIC_ALL, sa);

而且遗憾的是不工作,我得到以下错误:

System.Runtime.InteropServices.MarshalDirectiveException: Cannot marshal 'parameter #6': Invalid managed/unmanaged type combination (this value type must be paired with Struct).

任何想法我做错了吗?

Answer 1:

尝试改变参数#6

static extern IntPtr CreateDesktop(..., [In] ref SECURITY_ATTRIBUTES lpsa);

(此编译并不会引发在运行时异常,但我只用伪造的参数进行了测试。)

用C ++声明比较CreateDesktop :

HDESK WINAPI CreateDesktop(..., __in_opt LPSECURITY_ATTRIBUTES lpsa);
                                  ↑      ↑ ↑
                                  [In] ref SECURITY_ATTRIBUTES lpsa

LP代表“长指针”,即LPSECURITY_ATTRIBUTES是一个指向SECURITY_ATTRIBUTES结构。 因此,在C#中,你需要按引用传递你的结构实例(价值型)。



Answer 2:

请考虑使用以下原型改为:

    [DllImport("user32", EntryPoint = "CreateDesktopW", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern IntPtr CreateDesktop(string lpszDesktop, IntPtr lpszDevice, IntPtr pDevmode, int dwFlags,
                                              int dwDesiredAccess, IntPtr lpsa);

然后调用它只是创建一个固定手柄:

        GCHandle handle = GCHandle.Alloc(myStruct);
        try {
            IntPtr pinnedAddress = handle.AddrOfPinnedObject();
        }
        finally {
            handle.Free();
        }

这非常适用于呼叫PInvoke'd方法与结构。



文章来源: PInvoke CreateDesktop