PInvoke CreateDesktop - PullRequest
       20

PInvoke CreateDesktop

1 голос
/ 16 сентября 2009

Я пытаюсь 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).

Есть идеи, что я делаю не так?

Ответы [ 2 ]

5 голосов
/ 16 сентября 2009

Попробуйте изменить параметр # 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 # вам нужно передать свой экземпляр структуры (тип значения) по ссылке.

1 голос
/ 16 сентября 2009

Попробуйте использовать следующий прототип:

    [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 со структурами.

...