在 SSIS 包中使用 VB.NET,如何使用多个 Active Directory 域(在同一个林中)中的用户填充 SQL Server 表?
3 回答
我使用了类似于 Siva 方法的查询,除了链接服务器查询,我使用 ADSI 提供程序。Active Directory SSIS 数据源
SELECT
distinguishedName
, mail
, samaccountname
, Name
, employeeNumber
, objectSid
, userAccountControl
, givenName
, middleName
, sn
FROM
'LDAP://DC=domain,DC=net'
WHERE
sAMAccountType = 805306368
ORDER BY
sAMAccountName ASC
引用帖子中的代码将从给定域中提取所有用户。在从 NTEXT 转换为 TEXT 到 String 之后,我使用专有名称和 DirectoryServices 程序集通过其专有名称枚举用户的所有一阶组。它不涉及嵌套组。方便的是,该帖子涵盖了 2005 SSIS 实现,因此逻辑在 VB 中。
链接服务器方法:
设置链接服务器以连接到 Active Directory:
这是在 SQL Server 上使用Linked Server的一个可能选项,它实际上并不需要VB.NET
,如果您可以选择的话。下面给出的查询仅用于语法参考。请阅读链接以正确使用这些 SQL Server 对象。
您可以在 SQL Server 上设置链接服务器以使用OLE DB Provider for Microsoft Directory Services
. 下面是一个示例脚本,它将设置链接服务器并将其映射到可以访问 Active Directory 的登录名。
sp_addlinkedserver (Transact-SQL) 的使用
sp_addlinkedsrvlogin (Transact-SQL) 的使用
设置链接服务器的示例脚本:
USE [master];
GO
EXEC master.dbo.sp_addlinkedserver
@server = N'ADSI'
, @srvproduct = N'ADSI'
, @provider = N'ADsDSOObject'
, @datasrc = N'adsdatasource'
, @provstr = N'ADSDSOObject';
GO
EXEC master.dbo.sp_addlinkedsrvlogin
@rmtsrvname = N'ADSI'
, @useself = N'False'
, @locallogin = NULL
, @rmtuser = N'<User account goes here...>'
, @rmtpassword = '<Password goes here...>';
GO
使用 OpenQuery 查询 Active Directory:
然后,您可以使用 OpenQuery 查询 Active Directory 以获取用户信息。有关如何制定查询的更多信息,请阅读 MSDN 上的以下链接。
查询 Active Directory 的示例脚本:
SELECT *
FROM OPENQUERY
( ADSI
, ' SELECT *
FROM ''LDAP://<OU path goes here...>''
WHERE objectClass = ''user'''
);
如何在 SSIS 包中使用这些数据:
您可以将此查询设置为 SQL Server 视图,然后从SSIS 包中数据流任务上可用的OLE DB 源调用视图,然后将输出重定向到OLE DB 目标以填充数据库表。
带有 System.DirectoryServices 的脚本组件 (VB.NET)
这是一个示例逻辑,它在配置为Source的Script Component中借助 VB.NET 将 Active Directory 用户信息从一个域导入数据库表。此示例在 SSIS 2012 中进行了测试,但应该可以在 SSIS 2008 及更高版本中使用。此逻辑在 SSIS 2005 中不起作用,因为命名空间仅在 .NET Framework 3.5 中引入,而 SSIS 2005 使用 .NET Framework 2.0System.DirectoryServices.AccountManagement
创建一个 SSIS 包。此示例使用 SSIS 2012。
创建一个
OLEDB Connection Manager
将连接到 SQL Server 数据库的。如果您创建了数据源,请将数据源添加到包的连接管理器选项卡。将 a 拖放
Data Flow Task
到“控制流”选项卡上。双击
Data Flow Task
切换到数据流选项卡。将 a 拖放
Script Component
到“数据流”选项卡上。检查Select Script Component Type
Source
对话框并单击OK。双击脚本组件以打开脚本转换编辑器。点击
Inputs and Outputs
标签页。将输出重命名为 ActiveDirectory 以提供有意义的名称。
选择输出列并单击添加列以添加下面提到的每个列。这只是为了说明这个例子。您可能需要添加您喜欢的列。
脚本组件中的列定义
Name Data Type Length
----------------- ------------------------ ------
FirstName Unicode string [DT_WSTR] 255
LastName Unicode string [DT_WSTR] 255
SAMAccountName Unicode string [DT_WSTR] 255
UserPrincipalName Unicode string [DT_WSTR] 255
定义列后,点击
Script
标签页将 ScriptLanguage 更改为
Microsoft Visual Basic 2010
在解决方案资源管理器中,右键单击脚本组件项目并单击
Add Reference...
。添加对以下命名空间的引用。
脚本组件中要引用的命名空间
System.DirectoryServices
System.DirectoryServices.AccountManagement
- 将下面的 VB.NET 代码粘贴到脚本组件中。将该部分替换为
<Your domain name goes here>
您的适当域名。代码在方法中初始化PrincipalContext和PrincipalSearcher对象,PreExecute
然后在PostExecute
方法中释放它们。CreateNewOutputRows 方法循环遍历 AD 中找到的每一行以获取用户属性信息。
脚本组件代码 (VB.NET)
#Region "Imports"
Imports System
Imports System.Data
Imports System.Math
Imports Microsoft.SqlServer.Dts.Pipeline.Wrapper
Imports Microsoft.SqlServer.Dts.Runtime.Wrapper
Imports System.DirectoryServices.AccountManagement
Imports System.DirectoryServices
#End Region
<Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute()> _
<CLSCompliant(False)> _
Public Class ScriptMain
Inherits UserComponent
Dim principalContext As PrincipalContext = Nothing
Dim principalSearcher As PrincipalSearcher = Nothing
Public Overrides Sub PreExecute()
principalContext = New PrincipalContext(ContextType.Domain, "<Your domain name goes here>")
principalSearcher = New PrincipalSearcher(New UserPrincipal(principalContext))
MyBase.PreExecute()
End Sub
Public Overrides Sub PostExecute()
principalContext = Nothing
principalSearcher = Nothing
MyBase.PostExecute()
End Sub
Public Overrides Sub CreateNewOutputRows()
For Each principal As Principal In principalSearcher.FindAll()
Dim entry As DirectoryEntry = TryCast(principal.GetUnderlyingObject(), DirectoryEntry)
With ActiveDirectoryBuffer
.AddRow()
If entry.Properties("givenName").Value IsNot Nothing Then
.FirstName = entry.Properties("givenName").Value.ToString()
Else
.FirstName = "Unknown"
End If
If entry.Properties("sn").Value IsNot Nothing Then
.LastName = entry.Properties("sn").Value.ToString()
Else
.LastName = "Unknown"
End If
If entry.Properties("samAccountName").Value IsNot Nothing Then
.SAMAccountName = entry.Properties("samAccountName").Value.ToString()
Else
.SAMAccountName = "Unknown"
End If
If entry.Properties("userPrincipalName").Value IsNot Nothing Then
.UserPrincipalName = entry.Properties("userPrincipalName").Value.ToString()
Else
.UserPrincipalName = "Unknown"
End If
End With
Next
End Sub
End Class
关闭脚本转换编辑器。
将 OLE DB 目标拖放到“数据流”选项卡上。将脚本组件连接到 OLE DB 目标以重定向源输出。选择适当的 OLE DB 连接管理器和应插入数据的表。
改进这种方法的方法:
此示例仅提供来自一个域的加载信息。如果您有多个域,则可以将它们存储在一个表中。获取所有域列表的信息并使用Foreach Loop Container
控制流上可用的信息来循环遍历每个域并使用上述方法获取用户信息。可能还有更好的方法在 VB.NET 中执行此操作。
Active Directory 用户属性
您可以在下面的 MSDN 链接中找到 Active Directory 用户属性的完整列表。您需要单击链接以找到 LDAP-Display-Name。
这是另一个可能有助于获取用户对象属性的链接