You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 8迁移[LibraryImport]遇SYSLIB1051类型不支持问题求助

解决LibraryImport迁移中的SYSLIB1051错误

1. 修复TOKEN_PRIVILEGES结构体的 blittable 兼容性

SYSLIB1051错误的核心是源生成式P/Invoke(LibraryImport)仅支持 blittable 类型的结构体作为ref/out参数,非 blittable 类型(含引用类型、非值类型字段)无法自动封送。

首先修正TOKEN_PRIVILEGES及其依赖结构体的定义,确保所有字段为 blittable 值类型,并标记正确的内存布局:

[StructLayout(LayoutKind.Sequential)]
internal struct TOKEN_PRIVILEGES
{
    public int PrivilegeCount;
    public LUID_AND_ATTRIBUTES Privileges;
}

[StructLayout(LayoutKind.Sequential)]
internal struct LUID_AND_ATTRIBUTES
{
    public LUID Luid;
    public int Attributes;
}

[StructLayout(LayoutKind.Sequential)]
internal struct LUID
{
    public uint LowPart;
    public int HighPart;
}

修正后,原AdjustTokenPrivileges的LibraryImport定义可直接保留,源生成器会自动处理封送。

2. 手动封送送非 blittable 的STARTUPINFO结构体

STARTUPINFO包含string类型字段(非 blittable),无法直接作为ref参数传递,需改为传递IntPtr并手动处理内存封送:

步骤1:修改CreateProcessWithTokenW的LibraryImport定义

将ref STARTUPINFO替换为IntPtr:

[LibraryImport("advapi32.dll", SetLastError = true, StringMarshalling = StringMarshalling.Utf16)]
[return: MarshalAs(UnmanagedType.Bool)]
private static partial bool CreateProcessWithTokenW(
    IntPtr hToken,
    int dwLogonFlags,
    string lpApplicationName,
    string lpCommandLine,
    int dwCreationFlags,
    IntPtr lpEnvironment,
    string lpCurrentDirectory,
    IntPtr lpStartupInfo,
    out PROCESS_INFORMATION lpProcessInformation);

步骤2:手动处理结构体的内存分配与封送

调用API时,先分配非托管内存,将结构体复制到非托管堆,调用完成后释放资源:

// 初始化STARTUPINFO,必须设置结构体大小
var startupInfo = new STARTUPINFO();
startupInfo.cb = Marshal.SizeOf(startupInfo);

// 分配非托管内存
IntPtr startupInfoPtr = Marshal.AllocHGlobal(startupInfo.cb);
try
{
    // 将结构体复制到非托管内存
    Marshal.StructureToPtr(startupInfo, startupInfoPtr, false);
    
    // 调用CreateProcessWithTokenW
    bool success = CreateProcessWithTokenW(
        hToken,
        0, // 根据需求设置dwLogonFlags,如LOGON_WITH_PROFILE
        null, // 或指定应用程序路径
        "notepad.exe", // 目标进程命令行
        0, // dwCreationFlags
        IntPtr.Zero,
        null,
        startupInfoPtr,
        out var procInfo);
    
    // 处理调用结果
    if (!success)
    {
        int errorCode = Marshal.GetLastWin32Error();
        // 此处添加错误处理逻辑
    }
    else
    {
        // 关闭进程和线程句柄,避免资源泄漏
        CloseHandle(procInfo.hProcess);
        CloseHandle(procInfo.hThread);
    }
}
finally
{
    // 释放非托管内存
    Marshal.FreeHGlobal(startupInfoPtr);
}

补充:PROCESS_INFORMATION的正确定义

确保该结构体为 blittable 类型:

[StructLayout(LayoutKind.Sequential)]
internal struct PROCESS_INFORMATION
{
    public IntPtr hProcess;
    public IntPtr hThread;
    public int dwProcessId;
    public int dwThreadId;
}

3. 关键注意事项

  • 所有Win32辅助结构体的字段顺序、类型必须严格匹配原生定义,否则会导致内存布局错误。
  • 调用Marshal.StructureToPtr时,第三个参数设为false(新分配的内存无需清理原有数据)。
  • 调用完成后必须释放非托管内存并关闭Win32句柄,防止内存泄漏。

内容的提问来源于stack exchange,提问作者MHN

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 14:15:10