P/invoke函数将指针指向struct

Tim*_*ith 6 c# pinvoke winapi interop

诸如CreateProcess之类的函数具有指向结构的指针.在CI中,它只是NULL作为可选参数的指针传递,而不是在堆栈上创建虚拟结构对象并将指针传递给虚拟对象.

在C#中,我已将其声明为(p/invoke)

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        public static extern bool CreateProcess(
            string lpApplicationName,
            string lpCommandLine,
            ref SECURITY_ATTRIBUTES lpProcessAttributes,
            ref SECURITY_ATTRIBUTES lpThreadAttributes,
            bool bInheritHandles,
            CreateProcessFlags dwProcessCreationFlags,
            IntPtr lpEnvironment,
            string lpCurrentDirectory,
            ref STARTUPINFO lpStartupInfo,
            ref PROCESS_INFORMATION lpProcessInformation);
Run Code Online (Sandbox Code Playgroud)

但是,如果我试图通过nulllpProcessAttributes论点或lpThreadAttributes论据,我得到一个编译错误:

错误2参数3:无法从"<null>"转换为"ref Debugging.Wrappers.SECURITY_ATTRIBUTES"

如何修改上面的函数签名,以便我可以传递nullSECURITY_ATTRIBUTES参数,而不会出现此编译器错误?(如果我愿意,还能传递一个真正的结构?)

Tim*_*ith 6

好吧,我终于(!)找到了一个更好的方法:

将SECURITY_ATTRIBUTES声明为类而不是struct,并且不要通过ref传递它.:-)

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern bool CreateProcess(
        string lpApplicationName,
        StringBuilder lpCommandLine,
        SECURITY_ATTRIBUTES lpProcessAttributes,
        SECURITY_ATTRIBUTES lpThreadAttributes,
        bool bInheritHandles,
        CreateProcessFlags dwCreationFlags,
        IntPtr lpEnvironment,
        string lpCurrentDirectory,
        STARTUPINFO lpStartupInfo, /// Required
        PROCESS_INFORMATION lpProcessInformation //Returns information about the created process
        );

/// <summary>
/// See http://msdn.microsoft.com/en-us/library/aa379560(v=VS.85).aspx
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public class SECURITY_ATTRIBUTES
{
    public uint nLength;
    public IntPtr lpSecurityDescriptor;
    [MarshalAs(UnmanagedType.Bool)] public bool bInheritHandle;
}
Run Code Online (Sandbox Code Playgroud)

额外:这也允许你在SECURITY_ATTRIBUTES上声明一个体面的构造函数,它初始化nLength.


Mar*_*k H 3

null仅对 .Net 中的引用类型有效。您的 SECURITY_ATTRIBUTES 是 a struct,这是 a ValueType。您需要传递一个空的 SECURITY_ATTRIBUTES 结构,而不是传递 null。(只需说new SECURITY_ATTRIBUTES())在你的电话中。

更干净的方法是向结构添加静态 Empty 属性,然后传递SECURITY_ATTRIBUTES.Empty

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

    public static SECURITY_ATTRIBUTES Empty {
        get {
            return new SECURITY_ATTRIBUTES {
                nLength = sizeof(int)*2 + IntPtr.Size,
                lpSecurityDescriptor = IntPtr.Zero,
                bInheritHandle = 0,
            };
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

或者更好的是,不要使用 P/Invoke 创建 Process,而是检查该类System.Diagnostics.Process,它可能应该执行您需要的操作。