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

调用GetEffectiveRightsFromAcl触发AccessViolationException问题求助

问题排查与修复方案

核心问题分析

触发System.AccessViolationException的主要原因是TRUSTEE结构体的ptstrName字段处理错误,以及部分参数类型不匹配:

  1. SID传递方式错误
    当TrusteeForm设为TRUSTEE_IS_SID时,ptstrName字段实际需要的是指向SID结构体的指针(PSID),而非SID的字符串表示。你当前传入的SID.Value是字符串,导致非托管函数尝试将字符串指针当作SID指针解析,直接引发内存访问错误。

  2. 参数类型不匹配
    GetEffectiveRightsFromAcl的第三个参数pAclRights对应Win32的ACCESS_MASK类型,本质是unsigned int(32位无符号整数),用Int32(有符号)可能导致权限值溢出或解析错误。

  3. 字符集与Marshal属性不匹配
    TRUSTEE结构体指定了CharSet.Auto,但ptstrName用UnmanagedType.LPStr固定为ANSI字符串,当系统是Unicode环境时会出现编码不兼容问题;且当传递SID指针时,这个Marshal属性完全不适用。


修复后的代码

class Program
{
    const Int32 NO_MULTIPLE_TRUSTEE = 0;
    const Int32 TRUSTEE_IS_SID = 0;
    const Int32 TRUSTEE_IS_USER = 1;

    // 修正pAclRights类型为UInt32(对应ACCESS_MASK)
    [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    static extern UInt32 GetEffectiveRightsFromAcl(
        IntPtr pAcl,
        ref TRUSTEE pTrustee,
        ref UInt32 pAclRights);

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 4)]
    struct TRUSTEE
    {
        public IntPtr pMultipleTrustee;
        public Int32 MultipleTrusteeOperation;
        public Int32 TrusteeForm;
        public Int32 TrusteeType;
        // 当TrusteeForm为TRUSTEE_IS_SID时,此字段为PSID指针;为字符串时才是LPTStr
        public IntPtr ptstrName;
    }

    static void Main(string[] args)
    {
        var identity = new WindowsIdentity("company\\user1");
        IntPtr sidPtr = identity.User?.Value ?? throw new ArgumentException("User does not exist");
        
        IntPtr fileACLHandle = getFileSecurityHandle("C:\\temp\\test.txt"); // 确认返回的是PACL指针

        var trustee = new TRUSTEE
        {
            pMultipleTrustee = IntPtr.Zero,
            MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE,
            TrusteeForm = TRUSTEE_IS_SID,
            TrusteeType = TRUSTEE_IS_USER,
            ptstrName = sidPtr // 直接传入SID的指针,而非字符串
        };

        UInt32 aclRights = 0;
        UInt32 result = GetEffectiveRightsFromAcl(fileACLHandle, ref trustee, ref aclRights);
        if (result != 0)
        {
            Int32 hResult = Marshal.GetLastWin32Error();
            var ex = new Win32Exception(hResult);
            Console.WriteLine(ex.ToString());
            return;
        }

        Console.WriteLine($"Rights: {aclRights}");
    }

    // 假设你的getFileSecurityHandle实现正确返回PACL指针
    static IntPtr getFileSecurityHandle(string path)
    {
        // 此处保留你原有的正确实现
        throw new NotImplementedException();
    }
}

额外注意事项

  • 确保getFileSecurityHandle返回的是指向ACL结构的指针(PACL),而非其他安全对象指针(如PSECURITY_DESCRIPTOR),否则同样会引发内存错误。
  • 调用完成后,若需要手动释放非托管内存(如SID或ACL的内存),需确保正确调用对应Win32函数(如LocalFree)避免内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 00:45:40