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

求助:.NET Core中NTAccount.Translate失败后触发Safe handle已关闭异常的解决办法

解决.NET Core中域翻译失败后触发的Safe Handle已关闭异常问题

我之前也踩过这个坑,这确实是.NET Core早期版本(比如你提到的2.2.0搭配System.Security.Principal.Windows 4.5.1)里的一个棘手问题——当尝试翻译不存在的域账户抛出异常后,底层的安全句柄会被意外释放,导致后续所有相关的域名翻译调用全部失败,必须重启应用才能恢复功能。

问题根源

这个bug的核心在于NTAccount.Translate()方法在执行失败时,没有正确处理内部的安全句柄资源,导致后续调用复用了已经被释放的句柄,从而触发System.ObjectDisposedException。

可行的Workaround方案

这里有两个实用的解决思路,你可以根据项目情况选择:

1. 升级到较新的.NET Core稳定版本

最彻底的解决方案就是升级框架版本——这个句柄泄漏的问题在.NET Core 3.1及以后的版本中已经被官方修复了。如果你的项目允许升级,直接把Microsoft.NETCore.App升级到3.1或更高版本,同时同步更新System.Security.Principal.Windows到对应版本,就能一劳永逸解决这个问题。

2. 用独立进程隔离翻译操作(适合无法升级框架的场景)

如果暂时不能升级框架,我们可以利用进程间资源隔离的特性,把域名翻译逻辑放到一个独立的控制台工具中,主应用通过启动子进程来执行翻译操作。这样就算子进程因为无效域出错,也不会污染主应用的资源状态。

首先编写一个独立的翻译工具(比如命名为DomainTranslateTool.exe):

class Program
{
    static int Main(string[] args)
    {
        if (args.Length != 1)
        {
            Console.WriteLine("Invalid input");
            return 1;
        }

        try
        {
            var ntAccount = new NTAccount(args[0]);
            if (ntAccount.IsValidTargetType(typeof(SecurityIdentifier)))
            {
                var sid = (SecurityIdentifier)ntAccount.Translate(typeof(SecurityIdentifier));
                Console.WriteLine(sid.ToString());
                return 0; // 执行成功返回0
            }
        }
        catch
        {
            // 捕获所有异常,不输出错误信息
        }

        return 1; // 执行失败返回非0
    }
}

然后在主应用中调用这个工具:

static string TranslateDomain(string accountName)
{
    var processInfo = new ProcessStartInfo
    {
        FileName = "DomainTranslateTool.exe",
        Arguments = $"\"{accountName}\"", // 处理包含空格的账户名
        RedirectStandardOutput = true,
        RedirectStandardError = true,
        UseShellExecute = false,
        CreateNoWindow = true,
        WorkingDirectory = AppContext.BaseDirectory
    };

    using (var process = Process.Start(processInfo))
    {
        process.WaitForExit();
        if (process.ExitCode == 0)
        {
            return process.StandardOutput.ReadToEnd().Trim();
        }
        return string.Empty;
    }
}

测试验证

用你提供的测试代码替换Translate方法为上面的TranslateDomain,或者升级框架后运行:

static void Main(string[] args)
{
    var adminSid = new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, null);
    var adminAccount = adminSid.Translate(typeof(NTAccount));
    var validAccountName = adminAccount.ToString();

    foreach (var account in new[] { validAccountName, @"DOMAIN_NOT_EXISTS\Benutzer", validAccountName })
    {
        Console.WriteLine($"Testing: {account}");
        Console.WriteLine($"Result: {TranslateDomain(account)}\n");
    }
    Console.ReadKey();
}

你会发现,即使中间调用了不存在的域,最后一次对有效域名的翻译依然能正常返回结果,不会再抛出ObjectDisposedException。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:05:10