如何在SSIS(VS10)中获取AD用户memberof属性完整成员信息?
嘿,刚好我之前在SSIS(VS2010)里处理过一模一样的需求——获取AD用户的完整成员身份,输出成空格分隔的组DN格式,和你用dsget user "cn=...." -memberof命令得到的效果一致。给你分享两种靠谱的实现方式,你可以根据自己的习惯选:
方案1:在SSIS C#脚本转换中直接调用ADSI获取成员组
这种方法不需要依赖外部命令,直接在脚本里操作AD,稳定性和可控性更好。
- 打开脚本转换编辑器,先添加输入列(就是你存储用户DN的列,比如命名为
UserDN),再添加输出列(比如叫MemberOfGroups,数据类型选DT_WSTR,长度设4000足够用)。 - 在脚本编辑器的“引用”里,添加
System.DirectoryServices和System.DirectoryServices.AccountManagement两个程序集。 - 替换
Input0_ProcessInputRow方法为以下代码:
using System; using System.Data; using Microsoft.SqlServer.Dts.Pipeline.Wrapper; using Microsoft.SqlServer.Dts.Runtime.Wrapper; using System.DirectoryServices.AccountManagement; using System.Linq; [Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute] public class ScriptMain : UserComponent { private PrincipalContext _adContext; public override void PreExecute() { base.PreExecute(); // 初始化AD上下文,默认用当前域,也可以指定域名比如new PrincipalContext(ContextType.Domain, "yourdomain.com") _adContext = new PrincipalContext(ContextType.Domain); } public override void Input0_ProcessInputRow(Input0Buffer Row) { if (string.IsNullOrEmpty(Row.UserDN)) { Row.MemberOfGroups = string.Empty; return; } try { // 通过用户DN查找AD用户 using (UserPrincipal user = UserPrincipal.FindByIdentity(_adContext, IdentityType.DistinguishedName, Row.UserDN)) { if (user != null) { // 获取用户直接所属的所有组的DN,用空格拼接成目标格式 var groupDNs = user.GetGroups().Select(g => g.DistinguishedName); Row.MemberOfGroups = string.Join(" ", groupDNs); } else { Row.MemberOfGroups = string.Empty; } } } catch (Exception ex) { // 异常处理:可以输出空值,也可以用FireError记录错误日志 Row.MemberOfGroups = string.Empty; // ComponentMetaData.FireError(0, "GetADMemberOf", ex.Message, string.Empty, 0, out bool cancel); } } public override void PostExecute() { base.PostExecute(); _adContext.Dispose(); } }
如果需要获取嵌套组(用户所属组的父组),把user.GetGroups()换成user.GetAuthorizationGroups()就行,不过这个方法会返回所有授权组(包括内置组),按需调整。
方案2:在SSIS脚本中执行dsget命令并处理输出
如果你更习惯用dsget命令,也可以在脚本里调用cmd执行命令,再捕获输出处理成目标格式:
同样在脚本转换的Input0_ProcessInputRow方法里用以下代码:
using System; using System.Data; using Microsoft.SqlServer.Dts.Pipeline.Wrapper; using Microsoft.SqlServer.Dts.Runtime.Wrapper; using System.Diagnostics; using System.Text; using System.Linq; [Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute] public class ScriptMain : UserComponent { public override void Input0_ProcessInputRow(Input0Buffer Row) { if (string.IsNullOrEmpty(Row.UserDN)) { Row.MemberOfGroups = string.Empty; return; } try { // 构造dsget命令 string command = $"dsget user \"{Row.UserDN}\" -memberof"; ProcessStartInfo psi = new ProcessStartInfo("cmd.exe", $"/c {command}") { RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, CreateNoWindow = true, StandardOutputEncoding = Encoding.Unicode }; using (Process process = Process.Start(psi)) { string output = process.StandardOutput.ReadToEnd(); string error = process.StandardError.ReadToEnd(); process.WaitForExit(); if (!string.IsNullOrEmpty(error)) { Row.MemberOfGroups = string.Empty; return; } // 处理输出:跳过表头、空行,用空格拼接组DN string[] lines = output.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); var groupDNs = lines.Skip(1).Select(line => line.Trim()); Row.MemberOfGroups = string.Join(" ", groupDNs); } } catch (Exception ex) { Row.MemberOfGroups = string.Empty; // 异常处理逻辑 // ComponentMetaData.FireError(0, "ExecuteDsget", ex.Message, string.Empty, 0, out bool cancel); } } }
额外小贴士
- 确保SSIS运行的账户有AD的读取权限,否则会出现访问被拒绝的错误。
- 如果VS2010里引用
AccountManagement程序集有兼容性问题,可以改用更轻量的DirectoryEntry方式:using (DirectoryEntry userEntry = new DirectoryEntry($"LDAP://{Row.UserDN}")) { userEntry.RefreshCache(new[] { "memberOf" }); var groupDNs = userEntry.Properties["memberOf"].Cast<string>(); Row.MemberOfGroups = string.Join(" ", groupDNs); }
内容的提问来源于stack exchange,提问作者graphene
相关产品推荐
相关产品推荐

