以前收集到的一些资料---使用ADSI开发NT目录服务会出现的一些问题及解决办法(I)
发表于:2007-06-30来源:作者:点击数:
标签:
使用ASP 开发 NT目录服务会出现的一些问题(I) 有关ADSI的资料真是难找,技术虽然很好,可惜300多页的SDK我可真看不动 要是哪位大侠有空的话,能够帮我翻译就好了,呵呵。 现在只好将就着翻译一些短小的文章了,哎。匆忙之间翻译成的,错误肯定不 少,还希望大
使用ASP
开发NT目录服务会出现的一些问题(I)
有关ADSI的资料真是难找,技术虽然很好,可惜300多页的SDK我可真看不动
要是哪位大侠有空的话,能够帮我翻译就好了,呵呵。
现在只好将就着翻译一些短小的文章了,哎。匆忙之间翻译成的,错误肯定不
少,还希望大家谅解。
使用到的技术还是我前面提到的ADSI,这一节的重点放在操纵目录树上。
目录服务(DN)在贯穿了整个NT领域。几乎每一个管理任务最终都会
去改变系统目录中的某一个目录。象加入新用户到组里面,新建一个
互联网网站,或则更新电子邮件目录等等。注意的是,
Windows2000
的活动目录已经支持这个技术。
微软已经提供了一些功能很强大的COM接口来访问不同的目录服务。
ADS 命名空间和provider
ADS provider的概念和ODBC结构很相象,例如
Oracle的ODBC驱动器让一台机器连接到
Oracle的
数据库中,但是这并不意味着这个数据库确实存在。
同样的关系也使用与ADSI,它是一个适用与不同的目录命名空间的公共接口。
也许这个目录命名空间存在与
网络中。
在一个典型的
服务器上,当安装了正确的工具箱后,你会找到三个ADS provider
他们是:
WinNT: - 给NT及其网络用的
IIS: - 给IIS用的
LDAP: - 给MS Exchange和Windows200的活动目录用的
也许你还会发现下面的provider
NWCOMPAT: - 给Novell 3.1用的
NDS: - 给Novell Directory Services用的
每一个命名空间对象都由目录服务的根节点集组成,典型的例子是
NT的domain或者server,但不是所有的provider都能够自动发现根目录节点。
你能够绑定到一个WinNT:对象上它会提供一个NT域列表
但是对于IIS和LDAP的命名空间对象,则既没有IIS也没有MS Exchange的根节点.
在使用的时候而必须要被指明。
容器,会员,集合
对于大部分而言,目录是一个分层目录结构的对象同时它还包容了其他的对象
举例来说,一个物理的IIS服务器有多个网站,每个网站还可以有多个目录(
或则网站的运用程序),而这些目录还有子目录。
一个NT的domain能够有多个服务器等等。
在ADSI术语中,所有上面的容器对象又包容其它对象,就组成了命名空间树。
典型的代码如下:
Set oAds = GetObject("WinNT://MyDomain")
For Each oAdsChild in oAds
@# do something
Next
分层目录模型并不能够完全描述对象之间的关系。个别而言,NT的用户和组对象
约束与Domain 和 Server对象,但是他们之间又有一个附加的会员关系。
ADSI对象模型通过.Groups和.Menmbers属性来表示会员关系
例如一个典型的列表如下:
Set oAds = GetObject("WinNT://MyDomain/Administrator")
For Each oAdsGroup in oAds.Groups
@# do something
Next
@# ...
Set oAds = GetObject("WinNT://MyDomain/Domain Users")
For Each oAdsMember in oAds.Members
@# do something
Next
仔细观察上面的代码的微妙的不同之处
对一个对象本身执行列表,将返回它的子层。
对一个对象的.Member属性执行列表将返回它的会员列表。
最后,还有一些动态集合来表示那些暂时独立的对象。
一个典型的例子是在打印队列中的任务.PrintJobs集合
Schema对象
每个ADS对象都联系在一个SCHEMA对象,来表示它的
性能和特征
我们在写代码的时候经常碰到这样的问题:我的对象到底支持那些属性
这是一个容器对象,或则对象有可能包含什么样的类型。
例如,在原则上,一个目录服务本身就是一个彻底的SCHEMA对象。
准备运行程序
这个ADS浏览程序需要有一定的
安全权限才能够运行。
拷贝这个ADS浏览文件到你的网络中的一个共享的目录中
映射一个虚拟的web目录
指派这个目录有管理者的权限。
看一看命名空间树
在这里使用了微软的HtmlHelp Java applet.
它能够产生我们需要的树状结构。尤为重要的是它能够提供对子树的支持
因为我并不愿意拿我的整个目录树来冒险。
一个有关HtmlHelp applet的讨论会远远超出现在的话题,下面就只给出很简短的版本:
<UL>
<!-- ... -->
<LI>IIsWebServer Objects
<UL>
<LI> 1
<!-- on click: 显示页面
AdsProperties.asp?AdsPath=IIS://myserver/W3SVC/1} -->
<UL>
<!-- on expand: 显示下一级
AdsTreeHhc.asp?AdsPath=IIS://myserver/W3SVC/1 -->
</UL>
<LI> 2
<!-- on click: 显示页面
AdsProperties.asp?AdsPath=IIS://myserver/W3SVC/2} -->
<UL>
<!-- on expand: 显示下一级
AdsTreeHhc.asp?AdsPath=IIS://myserver/W3SVC/2 -->
</UL>
<!-- ... -->
</UL>
<!-- ... -->
</UL>
怎么找到目录树的节点
程序流程应该如下:
1。绑定到一个目录对象
2。查找与之关联的schema类
3。如果它是一个容器对象,那么
For all 可能的容器 in 这个对象 (通过schema得到)
对所有的对象进行实现
使用HtmlHelp applet生成<LI>...
在实现过程中,其实一共才10行代码,但是每一行代码都有起自己的难点
掌握了它们你就能够实现很多其它美妙的功能。
难点一:查找Schema类对象
第一个难点就是并不是所有的ADS对象都有真正有一个schema. 一段程序段如下
Set oAds = GetObject(vAdsPath)
Set oAdsClass = GetObject(oAds.Schema)
对于一些高一级的对象来说这段代码将会失败.必须再加一点异常处理。
Function GetClass(oADs)
On Error Resume Next
Set GetClass = Nothing
Set GetClass = GetObject(oADs.Schema)
End Function
Set oAdsClass = GetClass(oAds)
If Typename(oAdsClass) <> "Nothing" Then
@# do something
End If
通过管理一个schema类,我们查看它的.Container属性来决定我们处理的容器类型。
接着当我们使用它的.Containment数组来得到对象的类。
举例来说,一些Domain对象将返回一个schema类数组,其中包含有
字符串"Computer", "User", "Group", 和 "Schema".
理论上的代码如下
If oAdsClass.Container Then
vContainment = oAdsClass.Containment
For vIdx=0 to uBound(vContainment)
oAds.Filter = Array(vContainment(vIdx))
For Each oAdsChild in oAds
@# write an <LI>... entry
Next
Next
End If
但是又出现问题了,这个方法有时候不能够工作。一个WinNT Domain的.Containment数组
仅仅返回本来是4个对象类中的3个.而LDAP的provider根本就不执行.Container和.Containment属性
这样我们就没法再使用上面的代码了,只好针对这些怪异的现象造出一些怪异的代码了
其它奇怪的地方
下面是一些很怪异的代码,例如NT的LanmanServer对象可以想象它应该有一个FileService 类
并且包含有一个FileShare类对象.正确的代码如下:
Set oAds = GetObject("WinNT://MyDomain/MyServer/LanmanServer")
但是很不幸的是当我们调用它的父节点时将会出错
Set oAds = GetObject("WinNT://MyDomain/MyServer")
oAds.Filter = Array("FileService")
For Each oAdsChild in oAds
@# 这里的代码将永远不会执行
Next
下面类似的办法也会出错:
Set oAds = GetObject("WinNT://MyDomain/MyServer")
For Each oAdsChild in oAds
If oAdsChild.Name = "LanmanServer" Then
For Each oAdsGrandChild in oAdsChild
@# 出错
Next
End If
Next
这是为什么呢,其实LanmanServer有一个双重身份.它是一个FileService对象
但同时它也是一个普通的Service对象。所以下面这段怪异的代码就产生了:
For Each oAdsChild in oAds
If oAdsChild.Name = "LanmanServer" Then
Set oAdsChild = GetObject(oAdsChild.AdsPath)
For Each oAdsGrandChild in oAdsChild
@# 终于成功了
Next
End If
Next
对象性质:
同上面相比,对象的属性相对容易获得。每个对象可以想象得到都有一个核心的属性。
比如name,通过这个相同的属性能够很容易的使用对象:
vAdsName = oAds.Name
大多数对象还有这样的属性.MandatoryProperties 和 .OptionalProperties , 这都能够通过他们
的schema类得到,它们的数值可以通过对象的.GetEx方法得到:
For Each vProp in oAdsClass.MandatoryProperties
vPropValue = oAds.GetEx(vProp)
Next
原文转自:http://www.ltesting.net