首先介绍一下命名空间System.DirectoryServices
System.DirectoryServices 命名空间用以从托管代码简便地访问 Active Directory。该命名空间包含两个组件类,即DirectoryEntry 和 DirectorySearcher,它们使用 Active Directory 服务接口 (ADSI) 技术。ADSI 是 Microsoft 提供的一组接口,作为使用各种网络提供程序的灵活的工具。无论网络有多大,ADSI 都可以使管理员能够相对容易地定位和管理网络上的资源。
System.DirectoryServices 命名空间中的类可以与任何 Active Directory 服务提供程序一起使用。当前的一些提供程序包括 Internet 信息服务 (IIS)、轻量目录访问协议 (LDAP)、Novell NetWare 目录服务 (NDS) 和 WinNT。
ADSI 是 Microsoft Active Directory 的编程接口,使应用程序能够只使用一个接口就可以与网络上的不同目录进行交互。使用 ADSI,可以创建一些应用程序,用以执行常见任务,如备份数据库、访问打印机和管理用户帐户。
假定您在使用这些类之前已大致了解 Active Directory。有关 Active Directory 的更多信息,请参见主题“Introduction to Active Directory Objects”(Active Directory 对象介绍)和“Active Directory Technology Backgrounder”(Active Directory 技术背景介绍),以及位于 http://www.microsoft.com/china/msdn/library 上的 MSDN library 中的以下主题:
- Using Active Directory(使用 Active Directory)
- Active Directory Service Interfaces(Active Directory 服务接口)
- Lightweight Directory Access Protocol(轻型目录访问协议)
- Implementing Active Directory Service Interfaces Providers(实现 Active Directory 服务接口提供程序)
- Binding to an ADSI Object(绑定到 ADSI 对象)
- Binding String(绑定字符串)
IADsOpenDSObject::OpenDSObjectIADsOpenDSObject::OpenDSObject
Active Directory 是一种树结构。树中的每个节点包含一组属性。使用此命名空间可遍历、搜索和修改树,以及读取和写入节点的属性。
DirectoryEntry 类封装 Active Directory 层次结构中的节点或对象。使用此类绑定到对象、读取属性和更新特性。DirectoryEntry 与帮助器类一起为生存期管理和导航方法提供支持,包括创建、删除、重命名、移动子节点和枚举子级。
使用 DirectorySearcher 类对 Active Directory 层次结构执行查询。LDAP 是系统提供的唯一一种支持搜索的 Active Directory 服务接口 (ADSI) 提供程序。
通过 DirectorySearcher 搜索 Active Directory 层次结构将返回 SearchResult 的实例,这些实例包含在 SearchResultCollection 类的实例中。
DirectoryEntry的应用
DirectoryEntry组件提供了Path属性,根据文档,此属性指定了目录服务中用来访问对象的对象名,其格式如下:
protocol://servername:port number/distinguished name
此语句的第一部分定义了访问将使用的协议,如
LDAP: (Lightweight Directory Access Protocol)
IIS: (提供IIS元数据来读及配置Internet Infomation Server)
WinNT: (提供在非常有限的性能下对Windows NT域的访问)
NDS: (提供对Novell Directory Service的访问)
等等(详细信息清参考MSDN)。
Example_ONE:操作IIS
操作IIS时,DirectoryEntry的Path的格式为:IIS://ComputerName/Service/Website/Directory
ComputerName:即操作的服务器的名字,可以是名字也可以是IP,经常用的就是localhost;
Service:即操作的服务器,IIS中有Web,也有FTP,还有SMTP这些服务,我们主要是操作IIS的Web功能,因此此处就是"W3SVC",如果是FTP则应是"MSFTPSVC" ;
WebSite:一个IIS服务中可以包括很多的站点,这个就用于设置操作的站点。他的值是一个数字,默认是1,表示缺省站点,如果有其它,则从1开始依次类推;
Directory:操作的目录名称,一个站点一般顶层目录为"ROOT",其它目录则是他的孩子(Child)。
首先我们获取一个站点的顶层目录(根目录):
示例:
《创建虚拟目录》
DirectoryEntry rootfolder = new DirectoryEntry("IIS://localhost/W3SVC/1/ROOT");
如果我们创建这个对象是没有发生异常,则表示这个目录是真实存在的。
下面我们来添加新的虚拟目录,比如我们要加的是"ABC":
DirectoryEntry newVirDir = rootfolder.Children.Add("ABC","IIsWebVirtualDir");
newVirDir.Invoke("AppCreate",true);
newVirDir.CommitChanges();
rootfolder.CommitChanges();
创建目录的思路很简单,即在根目录的子集(rootfolder.Children)中再添加一条记录,这里使用的是DirectoryEntries类中的Add方法,它返回的是一个DirectoryEntry,表示新加入的目录,第一个参数是虚拟目录的名字,第二个则是Schema的类名以表明我们加入的目录类型。然后再使用DirectoryEntry的Invoke方法,调用ADSI中的"AppCreate"方法将目录真正创建,最后便是依次调用新、根目录的CommitChanges方法,确认此次操作。
《更新虚拟目录》
相信大家对IIS都比较熟悉,了解IIS中一些重要的设置,如可读(AccessRead)、可写(AccessWrite)、可执行(AccessExecute)等。这些都可通过对DirectoryEntry的Properties属性集合的赋值来实现。赋值可以通过两种方式来完成:
第一种是调用Properties集合的Add方法,如:
dir.Properties["AccessRead"].Add(true);
第二种是对第一个索引值赋值:
dir.Properties["AccessRead"][0] = true;
使用DirectoryEntries类的Find方法找到更新目标目录,如:
DirectoryEntry de = rootfolder.Children.Find("Aspcn","IIsVirtualDir");
比较常用的赋值属性有:AccessRead,AccessWrite,AccessExecute,AccessScript,DefaultDoc,EnableDefaultDoc,Path
《删除虚拟目录》
删除虚拟目录的方法也很简单,就是找到你要删除的虚拟目录,然后调用AppDelete方法。
DirectoryEntry de = rootfolder.Children.Find("Aspcn","IIsVirtualDir");
de.Invoke("AppDelete",true);
rootfolder.CommitChanges();
还有一种方法,就是调用Root目录的Delete方法。
object[] paras = new object[2];
paras[0] = "IIsWebVirtualDir"; //表示操作的是虚拟目录
paras[1] = "Aspcn";
rootfolder.Invoke("Delete",paras);
rootfolder.CommitChanges();
ExampleTWO:操作WinNT
引自张义的博客
本示例通过将DirectoryEntry的Path设为"WinNT:",然后对它的所有子项的枚举进行查看来发现网络上的所有域(以及工作 组)。这样,再对所发现的域(以及工作组)的子项进行枚举,就可以发现网络上的所有计算机。下面的一个控制台小程序演示了这一点。
- using System;
- using System.DirectoryServices;
- class TempClass
- {
- static void Main()
- {
- EnumComputers();
- }
- static void EnumComputers()
- {
- using (DirectoryEntry root = new DirectoryEntry("WinNT:"))
- {
- foreach (DirectoryEntry domain in root.Children)
- {
- Console.WriteLine("Domain | WorkGroup:/t" + domain.Name);
- foreach (DirectoryEntry computer in domain.Children)
- {
- Console.WriteLine("Computer:/t" + computer.Name);
- }
- }
- }
- }
- }
--------------------------------------------------------------------------------
改进后的Windows Forms方案
上面代码中两个嵌套的foreach循环看起来并不是太好,并且控制台的显示效果也并不那么美观。下面,我将对代码进行一些改动,并将它移植到WinForm上。
新建一个Windows Application[C#],在Form上添加一个TreeView,命名为treeView1。
添加以下几个函数:
- //用指定的文本构造一个节点,将其添加为参数parant的子节点,并返回刚构造的节点
- private TreeNode AddNode(TreeNode parant, string text)
- {
- TreeNode node = new TreeNode(text); parant.Nodes.Add(node); return node;
- }
- //递归地找到参数entry的所有子节点,并在treeView1中显示;这里的entry与entryNode需相对应
- private void EnumChildren(DirectoryEntry entry, TreeNode entryNode)
- {
- if (entry.Children != null) //如果无子节点则结束
- {
- foreach (DirectoryEntry i in entry.Children)
- { //将各子节点加入TreeView,并进行递归
- EnumChildren(i, AddNode(entryNode, i.Name));
- }
- }
- }
- //用给定的字符串构造根节点,并列出其所有子节点
- private void Enumerate(string path)
- {
- try
- {
- using (DirectoryEntry root = new DirectoryEntry(path))
- {
- TreeNode node = new TreeNode(root.Name);
- treeView1.Nodes.Add(node);
- EnumChildren(root, node);
- }
- }
- catch
- { }
- }
这样,通过传递 "WinNT:" 给函数Enumerate(string),就可以在TreeView中看到网络上的所有计算机,以及每台计算机上的用户、组、服务等资源,效果如图:
--------------------------------------------------------------------------------
总结
本文主要介绍了用DirectoryEntry配置IIS和查看局域网信息,在EXampleTWO中如果把“WinNT”改为“IIS”,我们还可以查看局域网中所有的IIS服务器的信息,DirectoryEntry的功能不仅仅限于此,因为它是对Active Directory的封装,所以ADSI能完成的功能它都可胜任,比如,还可以用它来对网络进行远程管理与配置等等。