P / invoke函数将指针指向struct
诸如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);
但是,如果我尝试为lpProcessAttributes
参数或lpThreadAttributes
参数传递null
, lpProcessAttributes
出现编译器错误:
错误2参数3:无法从“”转换为“ref Debugging.Wrappers.SECURITY_ATTRIBUTES”
如何修改上面的函数签名,以便我可以为SECURITY_ATTRIBUTES参数传递null
,而不会出现此编译器错误? (如果我愿意,还能传递一个真正的结构?)
null
仅对.Net中的引用类型有效。 您的SECURITY_ATTRIBUTES是一个struct
,它是一个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, }; } } }
或者更好的是,不是使用P / Invoke来创建进程,而是检查System.Diagnostics.Process
类,它应该可以满足您的需要。
好吧,我终于(!)找到了一个更好的方法:
将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 ); /// /// See http://msdn.microsoft.com/en-us/library/aa379560(v=VS.85).aspx /// [StructLayout(LayoutKind.Sequential)] public class SECURITY_ATTRIBUTES { public uint nLength; public IntPtr lpSecurityDescriptor; [MarshalAs(UnmanagedType.Bool)] public bool bInheritHandle; }
额外:这也允许你在SECURITY_ATTRIBUTES上声明一个体面的构造函数,它初始化nLength。