P/invoke 函数获取结构体指针

发布于 2024-09-08 10:43:36 字数 1127 浏览 6 评论 0原文

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,我得到编译器错误:

错误 2 参数 3:无法从“”转换参考 调试.Wrappers.SECURITY_ATTRIBUTES'

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

Functions such as CreateProcess have signatures taking pointers to structs. In C I would just pass NULL as a pointer for the optional parameters, instead of creating a dummy struct object on the stack and passing a pointer to the dummy.

In C#, I have 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 lpProcessAttributes argument or lpThreadAttributes argument, I get a compiler error:

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

How can I modify the above function signature so that I can just pass null for the SECURITY_ATTRIBUTES arguments, without this compiler error? (And also be able to pass a real struct if I want to?)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

一张白纸 2024-09-15 10:43:36

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

将 SECURITY_ATTRIBUTES 声明为类而不是结构,并且不通过引用传递它。 :-)

    [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;
}

额外的好处:这还可以让你在 SECURITY_ATTRIBUTES 上声明一个合适的构造函数来初始化 nLength。

OK, I finally(!) found an even better way of doing this:

Declare SECURITY_ATTRIBUTES as class instead of struct and don't pass it by 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: this also lets you declare a decent constructor on SECURITY_ATTRIBUTES which initializes nLength.

大姐,你呐 2024-09-15 10:43:36

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 创建 Process,而是查看 System. Diagnostics.Process 类,它可能应该执行您需要的操作。

null is only valid for Reference types in .Net. your SECURITY_ATTRIBUTES is a struct, which is a ValueType. Rather than passing null, you need to pass an empty SECURITY_ATTRIBUTES structure. (just say new SECURITY_ATTRIBUTES()) in your call.

A cleaner method is to add a static Empty property to your struct, and just 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 better yet, rather than using P/Invoke to create a Process, check out the System.Diagnostics.Process class, which should probably do what you need it to.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文