P / invoke function with structure pointer

Functions such as CreateProcess have labels containing pointers to structures. In C, I would simply pass NULL as a pointer to optional parameters, instead of creating a dummy structure object on the stack and passing a pointer to the mannequin.

In C #, I declared it as (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); 

But if I try to pass NULL for the argument lpProcessAttributes or lpThreadAttributes , I get a compiler error:

Error 2 Argument 3: Cannot convert from '<null>' to 'ref Debugging.Wrappers.SECURITY_ATTRIBUTES

How to change the above function signature so that I can just pass NULL for SECURITY_ATTRIBUTES arguments without this compiler error? (And also be able to convey the real structure if I want?)

+6
c # winapi interop pinvoke
source share
2 answers

null applies only to link types in .Net. your SECURITY_ATTRIBUTES is a struct which is a ValueType . Instead of passing null, you need to pass an empty SECURITY_ATTRIBUTES structure. (just say new SECURITY_ATTRIBUTES() ) in your appeal.

A cleaner method is to add the static Empty property to your structure and simply pass 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, }; } } } 

Or even better, instead of using P / Invoke to create the process, check out the System.Diagnostics.Process class, which should probably do what you need.

+3
source share

OK, I finally (!) Found an even better way to do this:

Declare SECURITY_ATTRIBUTES as a class instead of a structure and do not pass it by reference. :-)

  [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: it also allows you to declare a decent constructor on SECURITY_ATTRIBUTES, which initializes nLength.

+6
source share

All Articles