CreateProcess之类的函数具有指向结构的指针。在C中,我只是将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);
但是如果我尝试为null
参数或lpProcessAttributes
参数传递lpThreadAttributes
,我会收到编译错误:
错误2参数3:无法从'< null>'转换'参考 Debugging.Wrappers.SECURITY_ATTRIBUTES'
如何修改上面的函数签名,以便我可以为null
传递SECURITY_ATTRIBUTES参数,而不会出现此编译器错误? (如果我愿意,也能传递一个真正的结构?)
答案 0 :(得分: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;
}
Bonus:这也允许你在SECURITY_ATTRIBUTES上声明一个体面的构造函数,它初始化nLength。
答案 1 :(得分:3)
null
仅对.Net中的Reference类型有效。您的SECURITY_ATTRIBUTES是struct
,即ValueType
。您需要传递一个空的SECURITY_ATTRIBUTES结构,而不是传递null。 (在你的电话中说出new SECURITY_ATTRIBUTES()
)。
一个更清洁的方法是向你的struct添加一个静态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
类,它应该可以满足您的需要。