PInvoke创建桌面

发布于 2024-08-04 18:17:18 字数 1217 浏览 2 评论 0原文

我正在尝试以传递标志以由子进程继承桌面的方式来 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).

你知道我做错了什么吗?

I am trying to PInvoke CreateDesktop in a way that passes the flag to inherit the desktop by child processes. The declaration is as follows:

[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;
        }

And I use it as follows:

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);

And it unfortunately doesn't work, I get the following error:

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

Any ideas what I am doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

り繁华旳梦境 2024-08-11 18:17:18

尝试将参数 #6 更改为

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

(这会编译并且在运行时不会引发异常,但我仅使用虚假参数对其进行了测试。)

CreateDesktop

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

LP 代表“长指针” ,即 LPSECURITY_ATTRIBUTES 是指向 SECURITY_ATTRIBUTES 结构体的指针。因此,在 C# 中,您需要通过引用传递结构实例(值类型)。

Try changing parameter #6 to

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

(This compiles and doesn't throw an exception at runtime, but I've tested it only with bogus arguments.)

Compare with C++ declaration of CreateDesktop:

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

LP stands for "long pointer", i.e. LPSECURITY_ATTRIBUTES is a pointer to a SECURITY_ATTRIBUTES struct. So in C# you need to pass your struct instance (value type) by reference.

寻找一个思念的角度 2024-08-11 18:17:18

考虑使用以下原型:

    [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 方法非常有效。

Consider using the following prototype instead:

    [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);

Then to call it just create a pinned handle:

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

This works VERY well for calling PInvoke'd methods with structs.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文