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

C# Directory Services查询Active Directory每月随机出现本地错误问题

报错根因分析
  • 非托管资源泄漏:所有AD相关的PrincipalContext、UserPrincipal、PrincipalSearcher、PrincipalSearchResult以及遍历得到的UserPrincipal对象均实现了IDisposable接口,示例代码中未对上述对象做主动释放,长期运行会导致System.DirectoryServices依赖的底层COM非托管资源泄漏,资源耗尽时就会抛出本地错误,且泄漏的资源未被释放前,服务重启也无法重新申请到对应资源,导致重启失败。
  • 域查询中断:FindAll()是全量拉取域用户结果集,若域内用户基数大,查询遍历周期长,中途出现域控不可达、网络抖动、域控查询配额超限的情况,会导致枚举结果集时底层连接中断抛出异常。
  • 系统资源上限触发:未释放的资源会持续占用进程句柄、内存,当触及系统或服务进程的资源上限时,底层AD API调用会直接触发本地错误。
修复方案

代码优化

核心修复逻辑是对所有实现了IDisposable的AD相关对象做自动释放,修改后代码参考如下:

int userCount = 0;
DateTime now1 = DateTime.Now;
// 所有IDisposable对象用using语法自动释放
using (PrincipalContext AD = new PrincipalContext(ContextType.Domain, "ourdomain.org"))
using (UserPrincipal userPrincipal = new UserPrincipal(AD))
using (PrincipalSearcher search = new PrincipalSearcher(userPrincipal))
using (var all = search.FindAll())
{
    foreach (UserPrincipal result in all)
    {
        try
        {
            // 原有业务逻辑
            userCount++;
        }
        finally
        {
            // 遍历得到的每个Principal对象也要主动释放,避免残留资源
            result.Dispose();
        }
    }
}

额外优化措施

  • 若域用户量超过1000,建议配置DirectorySearcher的PageSize属性分页拉取结果,避免单次查询超时:
// 在PrincipalSearcher初始化后插入该配置
var underlyingSearcher = (DirectorySearcher)search.GetUnderlyingSearcher();
underlyingSearcher.PageSize = 1000;
  • 新增AD查询重试逻辑,遇到异常后先释放所有关联资源,等待3-5秒后再重试查询
  • 服务增加监控埋点,定期记录进程句柄数、内存占用,出现异常时同步记录域控连通性检测结果,方便后续定位触发边界条件

内容的提问来源于stack exchange,提问作者The Vanilla Thrilla

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.19 19:06:04