跟我从头学WSH(5)–理解ADSI
作者:qiqinghua
来源:青蛙的梦想
一。ADSI概览
(1)什么是ADSI
什么是ADSI
ADSI是一个应用程序接口,用来控制目录服务。
提供对目录服务对象的访问能力
使管理员对目录服务具备自动化的设置和管理能力。
支持多种目录服务供应商
LDAP,在Exchange 5.0 ldap ver 2
exchange 5.5 ldap ver 3
windows 2000 : adsldp.dll wldap32.dll
NDS:novell netware 4.0以上
Bindery Netware 3
(2) ADSI的优点
?容易使用
?名称空间的轻便性(对于不同的目录服务产品,有复用性)
?功能强大
ADSI提供了强有力的功能,使你可以开发出复杂的脚本解决方案
这些解决方法可以使包括简单的任务,比如在特定OU内找一个对象
或复杂的一些整个企业级的解决方案。
(3) ADSI结构
邦定:
ADSI客户首先必须找到(绑定)一个对象。ADSI客户可以是一个应用程序,比如脚本,定制程序或一个支持工具
The Provider
1。客户脚本或应用程序产生请求,绑定一个目录服务中的对象。
2。Provider创建一个ADSI对象,并且传递ADSI方法到目录服务。
3。目录服务对象数据被目录服务接收
4。目录服务对象的信息返回给provider
5。在客户应用程序的内存空间中,ADSI Provider创建一个ADSI实例。
6。对象方法现在可以为客户脚本所用了。
二。绑定到ADSI
(1) 绑定
绑定操作在客户的内存空间中创建一个对象。
Providers
ADSI提供4种不同的providers
Ads: 能够找到所有的安装在本地计算机上的可用providers.下面这个例子,如果企业使用一个新的provider叫“Newprov”,下面的代码将被插入到任何需要该非标准provider的脚本中。
Set objProviders = GetObject("ADs:")
For Each provider In objProviders
If provider.name = "NewProv:" Then
WScript.Echo "The required provider is installed"
WScript.Quit
End If
Next
WScript.Echo "The required provider is missing"
WScript.Quit
Bind语法
举例:
? To bind to the root of the WinNT namespace:
Set oMyObj = GetObject("WinNT:")
?To bind to the root of the LDAP namespace:
Set oMyObj = GetObject("LDAP:")
?To bind to the root of a specific Windows NT domain:
Set oMyObj = GetObject("WinNT://MyDomain")
?To bind to the root of a specific Windows 2000 domain:
Set oMyObj = GetObject("LDAP://MyDomain.com")
?To bind to the root of a specific Windows 2000 domain, by providing the class parameter:
Set oMyObj = GetObject("LDAP://DC=MyDomain, DC=com")
?To bind to the root of a specific Windows 2000 domain, by providing a computer name instead of the domain name:
Set oMyObj = GetObject("LDAP://MyServer")
?To bind directly to a specific computer with WinNT:
Set oMyObj = GetObject("WinNT://MyServer,computer")
?To bind directly to a specific computer with LDAP:
Set oMyObj = GetObject("LDAP://CN=MyServer,OU=Domain Controllers,DC=MyDomain,DC=com")
?Binding to a user object on a server with WinNT:
Set oMyObj = GetObject("WinNT://MyDom/MyServer/Alan,user")
?Binding to a user object on a server with LDAP:
Set oMyObj = GetObject("LDAP://MyServer.MyDom.com/CN=Alan,OU=CM,DC=MyDom,DC=com")
(2)不用服务器的绑定
不用服务器名的绑定
在前面所涉及的绑定,都要采用服务器名字的方法,但在有些时候,这样做不合适。
首选绑定方法
首先绑定方法被称为server-less binding. 这种方法,在代码中没有硬性的写出服务器的名字,下面的例子是绑定中采用了域名,但没有使用服务器名字,这种方法依靠windows 2000 DNS来绑定最佳服务器。
Set oMyObj = GetObject("LDAP://DC=MyDomain, DC=com")
优点:
?站点感知
?冗余
RootDSE绑定
如果你的脚本是运行在多域环境中,你必须使用”RootDSE”的对象来去除掉队硬性域名的需要
在绑定之前你可以使用RootDSE对象来解决当前域名。每一个windows 2000域控制器有一个唯一的RootDSE对象,可以用来提供信息(关于域内不同名称空间),用于脚本。
Set oRootDSE = GetObject("LDAP://RootDSE")
Set oMyDomain = GetObject( "LDAP://" &oRootDSE.Get("defaultNamingContext"))
WScript.echo oMyDomain.name
下面是最常见的RootDSE属性:
namingContexts Multi-valued. Distinguished names for all naming contexts stored on this directory server. By default,a Windows 2000 domain controller contains at least three namespaces: Schema, Configuration, and one for the domain that includes the server.
defaultNamingContext The distinguished name for the domain that includes this directory server.
schemaNamingContext The distinguished name for the schema container.configurationNamingContext The distinguished name for the configuration container.
RootDomainNamingContext The distinguished name for the first domain in the forest that contains the domain that includes this directory server.
SupportedLDAPVersion Multi-valued. LDAP versions (specified by major version number) supported by this directory server.
HighestCommittedUSN The highest USN used on this directory server. Used by directory replication.
DnsHostName The DNS address for this directory server
ServerName The distinguished name for the server object for this directory server in the configuration container.
currentTime The current time set on this directory server.
dsServiceName The distinguished name of the NTDS settings object for this directory server.
Global Catalog 服务器的绑定
如果你的脚本在多域环境(森林)中进行搜索,你可以绑定GC,
Set oGC = GetObject("GC://DC=MyDomain, DC=com")
(3)绑定一个信任状
绑定一个可选的信任状
在前面所有的例子中,ADSI的绑定都是使用当前登录用户的信任状,如果要不同的用户,则必须考虑。
绑定一个不同的用户:
ADSI提供了一个openDSObject方法来允许绑定不同的安全票证,来代替当前执行脚本用户的票证。
Set oMyDS = Getobject("LDAP:")
Set oMyObj = oMyDS.OpenDSObject( AdsPath, UserName, Password,ADS_SECURE_AUTHENTICATION)
(注意,在这种情况下,用户名和密码是以名文输入到脚本中的,这可能有安全隐患)
使用ADSI常量
三。ADSI对象
(1)对象方法
在完成了绑定操作后,对象的实例能够被脚本使用了。
脚本所用的方法提供既可以访问对象在内存中的实例和在目录中的对象。
Working with the Local Property Cache
用不着每次对一个对象的读写都要联系DC,ADSI缓存对象属性在客户端本地。
当你首次绑定一个对象(用GetObject)的时候,在缓存中该对象属性是空的,当你要获得属性的时候,ADSI自动获取该对象的所有属性值,并将其放置在缓存中。
下面列举了7种ADSI object methods,用于ADSI对象和本地属性缓存。
Get Retrieves the value of a property.
variable = oMyObj.Get("PropName")
GetEx Retrieves the values of a multivalue property.
Array() = oMyObj.GetEx("PropName")
Put Sets the value of a property.
oMyObj.Put "PropName", "Value"
PutEx Sets the values of a multivalue property.
oMyObj.PutEx ADSProp,"PropName",Array("Value1","Value2")
GetInfo Retrieves the values of all of the object’s properties from the directory service and puts them in the local property cache.
oMyObj.GetInfo
GetInfoEx Retrieves the values of the specified object’s properties from the directory service and puts them in the local property cache.
oMyObj.GetInfoEx Array("PropName"), 0
SetInfo Saves changes to an object’s properties back to the directory service.
oMyObj.SetInfo
下面的例子就是读取活动目录中对象的一个值
'Create an instance of an OU object from existing AD OU
Set oOU = GetObject _
("LDAP://cn=Admin10,OU=WST,DC=Microsoft,DC=local")
'Get a value from AD into the Local Property cache (LPC)
WScript.Echo oOU.PropertyCount ' 0 Properties cached
oOU.GetInfoEx Array("memberOf"), 0
WScript.Echo oOU.PropertyCount ' 1 Property cached
'Fill the Local Property Cache
oOU.GetInfo
WScript.Echo oOU.PropertyCount ' all Properties cached
'Get a value from the LCP
WScript.Echo oOU.Get("cn")
'Same as above using different method
WScript.Echo oOU.cn
'Get & echo a multivalued property from Local Property Cache
aMemberOf = oOU.GetEx("memberOf")
For Each grp In aMemberOf
WScript.Echo grp
Next
将信息写入目录
'Setup ADSI Constant
Const ADS_PROPERTY_APPEND = 3
'Create an instance of an OU object from AD
Set oOU = GetObject _
("LDAP://cn=Admin10,OU=WST,DC=Microsoft,DC=local")
'Update the local property cache value
oOU.Put"Description", "Cache Demo OU"
'Same as above using different method
oOU.Description, "Cache Demo OU again"
'Update LPC with a multivalue property
oOU.PutEx ADS_PROPERTY_APPEND, "otherTelephone", _
Array("(0)1234 5678900", "(0)0098 7654321")
'Write the local property cache back to AD
oOU.SetInfo
在举例里,ADSProp是一个常量,用来指示值如何被更新。
ADS_PROPERTY_CLEAR 1
ADS_PROPERTY_UPDATE 2
ADS_PROPERTY_APPEND 3
ADS_PROPERTY_DELETE 4
(2)对象属性
六个标准属性
Name The name of the object.
Class The schema class name of the object.
GUID A globally unique identifier structure that uniquely identifies the object.
AdsPath The string form of the object’s path in the directory service. This path uniquely identifies the object.
Parent The ADsPath name of the object’s parent container.
Schema The ADsPath of this object’s schema class object.
下面例子是显示标准的属性
Set oMyObj = GetObject("LDAP://ou=WST,dc=contentm,dc=com")
WScript.Echo "Name is " & oMyObj.Get "Name"
WScript.Echo "Class is " & oMyObj.Get "Class"
WScript.Echo "GUID is " & oMyObj.Get "GUID"
WScript.Echo "ADsPath is " & oMyObj.Get "ADsPath"
WScript.Echo "Parent is " & oMyObj.Get "Parent"
WScript.Echo "Schema is " & oMyObj.Get "Schema“
获取其它的属性
Set oMyUser = _
GetObject("LDAP://cn=UserName,ou=WST,dc=contentm,dc=com")
WScript.Echo "The full name is = " & oMyUser.Get("FullName")
读取多属性:你可能需要列出所有的属性,你可以采用propertycount和item方法来显示:
Option Explicit
Dim objGroup, i, sPropList, count
On Error Resume Next
Set objGroup = _
GetObject("LDAP://cn=Admin10,ou=WST,dc=NWTraders,dc=msft")
objGroup.GetInfo
i = objGroup.PropertyCount
sPropList = "There are " & i _
& " values in the local property cache:" & vbCrLf & vbCrLf
For count = 0 To (i-1)
sPropList = sPropList & objGroup.Item(CInt(count)).Name _
& vbCRLF
Next
WScript.Echo sPropList
Script Uses Schema Names, Not Display Names
你用前面的示例代码,你会发现返回的属性名称和Active Directory User and computer显示的不同,这是因为在示例中使用的是schema name,而不是display name.
我们可以使用adsvw.exe工具来显示schema names.
四。查找活动目录
(1)搜索活动目录
使用ADO进行活动目录搜索
使用ADO进行查找
ADO是一个简单有效的执行活动目录查找的途径。当执行一个查找时,经常要用到三个ADO对象:
Connections: 用来指定provider名称,可选信任状和其它标记
Command: 指定查找参数和查询字符串
Recordset:表现结果集
内置LDAP查询语句
要使用ADO搜索活动目录,你必须首先理解LDAP语句查询结构,下面显示通常的查询语句串:
"<FQADsPath>;(Filter);Attributes;Scope"
Name Symbol
Logical AND &
Logical OR |
Logical NOT !
Equal to =
Approx equal to ~=
Greater than >=
Less than <=
LDAP://DC=NWTraders,DC=msft>;(&(objectCategory=Person) _
(objectClass=user));name,telephonenumber;subTree
在这个例子里,只返回对象类别是person和类型user的值
你也可以使用通配符,比如
(ObjectClass=*)
?Base
Search the object itself.
? OneLevel
Extend the search to the immediate children of the object, but exclude the bas e object itself.
? Subtree
Extend the search down to multiple sublevels of the object, and include the base object.
If no scope is specified, the search will default to a Subtree search.
(2)使用单连接进行多项查询
这个脚本显示所有在NWTraders.msft域中的用户的名字和电话号码。
'Create connection and command object
Set con = CreateObject("ADODB.Connection")
Set com = CreateObject("ADODB.Command")
'Open the connection with the ADSI-OLEDB provider name
con.Provider = "ADsDSOObject"
con.Open
'Assign the command object for this connection
Com.ActiveConnection = con
'Create a search string
Com.CommandText = "<LDAP://DC=NWTraders,DC=msft>;" _
& "(objectClass=user);name,telephonenumber;subTree"
'Execute the query
Set rs = Com.Execute()
'Navigate the record set
Do Until rs.EOF
'Build Result Text
sResultText = sResultText & rs.Fields("Name") & " , " _
& rs.Fields("telephonenumber") & vbCrLf
rs.MoveNext
Loop
WScript.Echo sResultText
(3)为每个查询建立连接
这个ADO查找AD的举例可以比前面的脚本例子更快。因为它简单的创建了一个ADODB Recordset实例,然后用它连接一个基于查找的单行脚本。
关键是加了
, "provider = ADsDSOObject"
这个实例的不好的地方是每次查询执行都要建立新的连接。如果在一个脚本中有多次查询,前面的示例更有效。
五。创建新的ADSI对象
(1)创建新的OU
使用ADSI创建OU是一个简单任务
第一行创建一个对象oRootDSE,返回一个连接到当前目录服务的根
使用oRootDES的Get方法创建一个新的对象叫oDOM,这个大局ixiang关联到默认的域的名称上下文。
使用oDOM对象的create方法创建一个新的OU,名字叫oOU,名字叫HQ,名字是强制属性
注意的是,这个对象还没有提交到AD,要保存到目录服务,使用SetInfo方法。
(2)创建新用户
创建一个新的用户
下面的例子是在HQ OU中创建一个新的用户
Set oOU = GetObject ("LDAP://OU=HQ,DC=lab,DC=contentm,DC=com")
Set oUSR = oOU.Create("user", "CN=Alan Steiner")
oUSR.Put"samAccountName", "Alan"
oUSR.Put "userPrincipalName", "[email protected]"
oUSR.SetInfo
oUSR.SetPassword "TempPassword"
oUSR.AccountDisabled = False
oUSR.SetInfo
注意,在这个例子中,提交了两次,这是因为属性SetPassword和AccountDisable只能用于这个对象已经存在的情况。
(3)创建新组
组类型
安全组和分布组
组的方法和属性
Property Description
Description Provides a place for a string comment about the group
Method Description
Members Returns a collection of the group’s members
IsMember Returns True if the given ADsPath is a member of the group
Add Adds the given ADsPath to the group
Remove Removes the given ADsPath from the group
' Setup Constants
Const ADS_GROUP_TYPE_GLOBAL_GROUP = &H2
Const ADS_GROUP_TYPE_DOMAIN_LOCAL_GROUP = &H4
Const ADS_GROUP_TYPE_LOCAL_GROUP = &H4
Const ADS_GROUP_TYPE_UNIVERSAL_GROUP = &H8
Const ADS_GROUP_TYPE_SECURITY_ENABLED = &H80000000
' Bind to OU
Set oOU = GetObject("LDAP://OU=WST,DC=NWTraders,DC=MSFT")
' Create new group
Set oGroup = oOU.Create("group", "CN=Script Users")
' Set the group type
oGroup.Put "groupType", ADS_GROUP_TYPE_DOMAIN_LOCAL_GROUP Or _
ADS_GROUP_TYPE_SECURITY_ENABLED
' Set the group properties
oGroup.Put "sAMAccountName", "Script Users"
oGroup.Put "name", "Script Users"
oGroup.Put "displayName", "Script Users"
oGroup.Put "description", "Script Users Security Group"
' Save back to the AD
oGroup.SetInfo
这里注意的是ADSI常量
Constant Value
ADS_GROUP_TYPE_GLOBAL_GROUP &H2
ADS_GROUP_TYPE_DOMAIN_LOCAL_GROUP &H4
ADS_GROUP_TYPE_LOCAL_GROUP &H4
ADS_GROUP_TYPE_UNIVERSAL_GROUP &H8
ADS_GROUP_TYPE_SECURITY_ENABLED &H80000000
增加用户到组
oGroup.Add ("LDAP://cn=MyUser,ou=WST,dc=NWTraders,dc=msft,
LDAP://cn=MyUser2,ou=WST,dc=NWTraders,dc=msft,
LDAP://cn=MyUser3,ou=WST,dc=NWTraders,dc=msft")
从组中移走用户
oGroup.Remove ("WinNT://NWTraders/WST/MyUser")
六。在活动目录中设置安全
安全组件:每个活动目录对象都有相应的安全描述符,使得你可以编辑和传播权限,执行审核。
每个安全描述有两个访问控制列表(DACL和SACL),每个ACL由ACE组成
每个ACE包含下面的组件:
AccessMask
AceType
AceFlags
Trustee
Flags
要用脚本实现操作安全,你应该提及Windows 2000 Platform Software Developers Kit.
虽然可以使用script在活动目录中操作安全,但更容易使用的工具是Dsacls.exe,它随windows 2000 support tools提供。
七。 使用ADSI管理共享
Binding to the lanmanserver service
Set oLMServer = GetObject("WinNT://MyComputer/LanManServer")
绑定完成后,下列方法可用:
Property Description
Name The share name
CurrentUserCount The number of users currently connected to the share (read-only)
Description The friendly description for the file share
HostComputer The ADsPath for the computer where this share resides
MaxUserCount The maximum number of users that are allowed to connect to this share simultaneously
Path The local file system path for the shared folder
下面的脚本列举在”MyComputer”计算机上的所有共享
Set oLMServer=GetObject("WinNT://MyComputer/LANMANSERVER")
For Each share in oLMServer
WScript.Echo share.Name & " = " & share.Path
Next
下面的脚本在”mycomp”计算机上设置共享
Name = DemoShare
Path = C:\Temp
Description = “This is a demo share”
User Limit = 5
Set oLMServer=GetObject("WinNT://MyComp/LANMANSERVER")
Set oNewShare = oLMServer.Create("fileshare", "DemoShare")
oNewShare.Path = "C:\Temp"
oNewShare.Description = "This is a demo share"
oNewShare.MaxUserCount = 5
oNewShare.SetInfo
这个脚本并没有设置共享权限,一个可行的解决方案时采用resources kit中的Permcopy来实现
八。列举计算机上的服务
列举计算机上的服务
Option Explicit
Dim objComputer, Service, strSvrList
Set objComputer = GetObject("WinNT://MyServer")
strSvrList = "The Services on " & objComputer.ADsPath _
& " are " & vbCrLf
For Each Service in objComputer
If Service.Class = "Service" Then
strSvrList = strSvrList & Service.Name & vbCrLf
End If
Next
WScript.Echo strSvrList
常量
ADS_SERVICE_STOPPED = &H1
ADS_SERVICE_START_PENDING = &H2
ADS_SERVICE_STOP_PENDING = &H3
ADS_SERVICE_RUNNING = &H4
ADS_SERVICE_CONTINUE_PENDING = &H5
ADS_SERVICE_PAUSE_PENDING = &H6
ADS_SERVICE_PAUSED = &H7
ADS_SERVICE_ERROR = &H8
列决计算机上运行的服务:
Option Explicit
Const ADS_SERVICE_RUNNING = &H4
Dim objComputer, Service, strSvrList
Set objComputer = GetObject("WinNT://MyServer")
strSvrList = "The Services on " & objComputer.ADsPath _
& " are: " & vbCrLf
For Each Service in objComputer
If Service.Class = "Service" Then
If Service.Status = ADS_SERVICE_RUNNING Then
strSvrList = strSvrList & Service.Name & vbCRLF
End If
End If
Next
WScript.Echo strSvrList
启动服务:
Set oBrowser = GetObject("WinNT://MyServer/browser")
oBrowser.start
关闭服务:
Set oMessenger = GetObject("WinNT://MyServer/messenger")
oMessenger.stop
九。ADSI资源
ADSI资源
Platform SDK
提供全面的资源,主要的程序。ADSI Developers Guide是SDK的有价值的参考的一部份。