Active Directory Service Interface

Active Directory Service Interface (ADSI) 是一组植基于 COM 技术上的应用程式开发介面，程式开发人员可以利用这些介面来连接并存取 Active Directory，并执行查询，更新或删除等管理功能，ADSI同时可支援以LDAP（轻量级目录存取协定）为主的目录服务（例如Novell Directory Service），以及以 Windows NT 网域为主所组成的 WinNT 网域目录。

**介面结构**
ADSI 由 COM 以及原生函式库所组成，并封装在 activeds.dll 档案中，部份则被封装在 advaip32.dll 中，以 COM 原生介面方式呈现，以提供给 C/C++ 程式语言透过 COM 介面来取用，不过由于所有的原生介面均支援 COM Automation，因此 Visual Basic 或是 .NET Framework 的语言也可以利用 COM Interop 能力存取 ADSI 中的介面。

**原生介面 (Native interfaces)**
activeds.dll 中封装了几个 ADSI 中最核心的介面：- IADs：作为所有 Active Directory 物件最顶层的介面，拥有最基础的功能，- IADsContainer：作为所有可收纳 Active Directory 物件的收纳器 (Container) 最顶层的介面，具有收纳器的基础功能。- IADsOpenDSObject：连接 Active Directory 之用（它只有 OpenDSObject() 一个方法），同时它会快取住用来连接的安全资讯内容。- IADsNamespace：由目录服务提供者 (directory service provider) 提供，用来识别目录结构的命名空间之用。
activeds.dll 亦提供了几个依物件不同而实作的介面，像是：- IADsComputer：提供目录服务中的电脑 (computer) 物件。- IADsDomain：提供目录服务中的网域 (domain) 物件。- IADsUser：提供目录服务中的使用者 (user) 物件。- IADsGroup：提供目录服务中的使用者群组 (group) 物件。- IADsOU：提供目录服务中的组织单元 (organization unit) 物件。- IADsCollection：提供目录服务物件集合。
在使用 ADSI 之时，有时会需要一些工具型功能，像是 DOMAIN\user 和 User Principal Name 间的转换，或是取得系统资讯等，ADSI 也提供了这类的介面：- IADsNameTranslate：在目录服务中在不同的名称间转换。- IADsWinNTSystemInfo：在目录服务中取得 Windows NT Directory Service 系统资讯。- IADsADSystemInfo：在目录服务中取得 LDAP Directory Service 系统资讯。- IADsPathname：剖析 X.500 名称与路径。
这些介面多是使用 C/C++ 程式语言来存取，若是使用 VB 或是 Scripting Language 时，则可以使用另外的方法来存取。
' Get user object from Active Directory.
Dim mach As IADsContainer
Dim usr as IADsUser
On Error GoTo Cleanup
Set mach = GetObject("WinNT://MyMachine,Computer")
Set usr = mach.Create("user","jeffsmith")
usr.SetInfo
Cleanup:
If(Err.Number0) Then
MsgBox("An error has occurred. " & Err.Number)
End If
Set mach = Nothing
Set usr = Nothing
// binding Active Directory using C++ and native interface.
IADs *pObject;
HRESULT hr;
// Initialize COM.
CoInitialize(NULL);
hr = ADsGetObject(L"LDAP://CN=jeffsmith,DC=fabrikam,DC=com", 
IID_IADs,
(void**) &pObject);
if(SUCCEEDED(hr))
{
// Use the object.
// Release the object.
pObject->Release()
}
// Uninitialize COM.
CoUninitialize();

**函式**
ADSI 除了介面以外，也将部份功能使用函式方式显露，以简化呼叫原生介面需要处理的工作，较重要且经常被使用的有：- ADsOpenDSObject()，封装取得 IADs 或 IADsContainer 等物件的工作。- ADsGetObject()，封装利用已开启的 Active Directory Session 取得物件的工作。- ADsGetLastError()，取得在 ADSI 作业中，最后一个引发的错误。- AllocADsMem(), FreeADsMem(), AllocADsStr(), FreeADsStr()，配置与释放 ADSI 使用的资源。- ADsBuildEnumerator(), ADsEnumerateNext(), ADsFreeEnumerator()：处理 ADSI 物件的列举工作。
下列的例子，是使用 ADsOpenDSObject() 取得 IADs 物件的范例程式码：
IADs *pObject;
LPWSTR szUsername = NULL;
LPWSTR szPassword = NULL
HRESULT hr;
// Insert code to securely retrieve the username and password.
hr = ADsOpenObject(L"LDAP://CN=Jeff,DC=Fabrikam,DC=com",
"jeffsmith",
"etercespot",
ADS_SECURE_AUTHENTICATION, 
IID_IADs,
(void**) &pObject);

**.NET Framework 原生介面**
在 .NET Framework 中，另外提供了一个 .NET 专用的 ADSI 介面程式库 System.DirectoryService.dll，程式开发人员可以加入此程式库的参考来取得 ADSI 的功能，在这个原生类别库中，封装了两个类别，作为存取 Active Directory 的入口之用。- DirectoryEntry：此类别封装了 IADs 以及 IADsContainer 等原生介面，用来存取 Active Directory 的物件资料，以及 Schema 封装的资讯等等。- DirectorySearcher：此类别封装了 IDirectorySearch 介面，作为搜寻 Active Directory 的主要工具，并使用 SearchResult 物件封装搜寻结果，让 .NET 开发人员可以简化处理搜寻结果的工作。
截至 .NET Framework 3.5 为止，ADSI 在 Managed Class Library 中有四个命名空间：- System.DirectoryServices：原生的 ADSI Managed 介面，封装 DirectoryEntry 和 DirectorySearcher 与工具类别。- System.DirectoryServices.AccountManagement：封装对 IADsUser, IADsComputer, IADsGroup 等介面，简化处理物件的工具。- System.DirectoryServices.ActiveDirectory：封装对 Active Directory 结构物件的工具。- System.DirectoryServices.Protocol：封装对 LDAP 协定与目录服务通讯的工具与基础类别。
下列为使用 C# 存取 DirectoryEntry 的范例程式码：
DirectoryEntry ent = new DirectoryEntry();
DirectoryEntry ou = ent.Children.Find("OU=Consulting");
// Use the Add method to add a user to an organizational unit.
DirectoryEntry usr = ou.Children.Add("CN=New User","user");
// Set the samAccountName, then commit changes to the directory.
usr.Properties"samAccountName".Value = "newuser"; 
usr.CommitChanges();

**目录服务提供者 (directory service provider)**
ADSI 因为是使用了 LDAP 以及开放式目录等标准，因此只要目录服务的平台是以开放式目录标准实作 IADsNamespace 与其他目录服务提供者介面时，即可由 ADSI 来支援，目前 ADSI 有五种提供者：- ADSI LDAP Provider：Active Directory 官方主要的支援介面，连接字串使用 LDAP:// 为主。- ADSI WinNT Provider：以 Windows NT 为主的支援介面，连接字串使用 WinNT:// 为主。- ADSI NDS Provider：支援 Novell Directory Service，连接字串使用 NDS:// 为主。- ADSI NWCOMPAT Provider：支援 Novell Netware 3.x 的网路服务，连接字串使用 NWCOMPAT:// 为主。- ADSI IIS Provider：支援 IIS 内部的提供者，连接字串以 IIS:// 为主，用于存取 IIS Metabase。

**OLE DB Provider for Directory Services**
除了 ADSI 原生介面外，微软也为了 SQL Server 或是 ADO 应用程式开发人员发展了可使用 ADO 来存取 Active Directory 的驱动程式，此驱动程式使用 OLE DB 来开发，并且使用类似 SQL 指令的方式来存取 Active Directory，此驱动程式称为 OLE DB Provider for Directory Service，其 COM 的 Prog ID 为 ADsDSOObject。
下例为使用 ADO 存取 Active Directory 的范例程式码：
Dim Con As New Connection
Dim rs As New Recordset
Dim command As New Command
Dim usr As IADsUser
' Replace department for all users in OU=sales.
Set con = Server.CreateObject("ADODB.Connection")
con.Provider = "ADsDSOObject"

Set command = CreateObject("ADODB.Command")
Set command.ActiveConnection = con

command.CommandText = "SELECT AdsPath, cn FROM 'LDAP://OU=Sales,DC=Fabrikam,DC=com' WHERE objectClass = 'user'"

command.Properties("searchscope") = ADS_SCOPE_ONELEVEL
Set rs = command.Execute
While Not rs.EOF
Set usr = GetObject(rs.Fields("AdsPath").Value)
usr.Put "department", "1001"
usr.SetInfo
rs.MoveNext
Wend
下列指令为使用 SQL Server 查询来合并存取 Active Directory 的指令码：
-- create a linked server to active directory interface
EXEC sp_addlinkedserver 'ADSI', 'Active Directory Services 2.5', 'ADSDSOObject', 'adsdatasource' 
-- configure SQL Server to allow ad-hoc query and openquery statement.
EXEC sp_configure 'show advanced options', 1
reconfigure with override
EXEC sp_configure 'Ad Hoc Distributed Queries', 1 
reconfigure 
-- execute query via OpenQuery() statement
SELECT * FROM OpenQuery(ADSI, 'SELECT * FROM LDAP://DC=kodyaz,DC=com WHERE objectCategory=user ') 
SELECT * FROM OpenQuery(ADSI, 'SELECT mail, displayName, userPrincipalName FROM LDAP://DC=kodyaz,DC=com WHERE objectCategory=user ') 

**开发 Directory-Enabled 应用程式时可用的工具**
由于 ADSI 和 Active Directory 的特性，开发人员若没有使用适当的工具时，很难发展与目录服务连结 (directory-enabled) 的应用程式，因此微软为 Active Directory 提供了两种工具：- Active Directory Explorer：由 Sysinternals 团队所开发，现已并入 Microsoft TechNet 团队中，可用来浏览 AD 网域或树系的 LDAP 阶层字串，以及物件的属性资料。- ADSIEdit：在 Windows 2000 和 Windows Server 2003 时，由 Resource Kit Support Tools 安装包提供，到了 Windows Server 2008 时，则内建在系统中。

**参考资料**
内容参考：
文章参考：
#  MSDN Library: Active Directory Service Interfacedate=20080510114524 
#  Directory Service in .NET Frameworkdate=20090112153209