Sie sind auf Seite 1von 18

Scripting with rootDSE

Microsoft® Windows® 2000 Scripting Guide

Using rootDSE involves three basic steps.

1. Bind to rootDSE.

2. Use the Get method to read an attribute of rootDSE.

3. Use the attribute returned by rootDSE to construct an ADsPath and bind to a container or an object in the
directory.

Steps 2 and 3 are often combined to reduce the length of the script.

The goal of the four scripts in this section is to demonstrate how to use rootDSE to bind to the current domain, the root
domain, the configuration container, and the schema container. Using rootDSE to form an ADsPath to the current domain,
the root domain, and the configuration container is useful for the previous script examples in this chapter. Using rootDSE
to form an ADsPath to the schema container is useful for the scripts appearing in the upcoming section "Active Directory
Architecture."

Binding to the Current Domain

The script in Listing 5.42 binds to the current domain by using the defaultNamingContext attribute of rootDSE. The current
domain is the domain where the client is logged on. This example is particularly useful for the numerous listings in this
chapter that access the current domain. By modifying the binding string, you can also use this example for binding to a
common container such as the Users container, an OU, or any leaf object in the domain. To carry out this task, the script
performs the following steps:

1. Bind to the rootDSE.

2. Construct an ADsPath to the current domain.

3. Use the strADsPath variable in the binding operation.

Listing 5.42 Constructing an ADsPath to the Current Domain with rootDSE

1
Set objRootDSE = GetObject("LDAP://rootDSE")
2
3 strADsPath = "LDAP://" & objRootDSE.Get("defaultNamingContext")
Set objDomain = GetObject(strADsPath)

In the na.fabrikam.com domain, the strADsPath variable contains:

LDAP://DC=na,DC=fabrikam,DC=com

Binding to the Root Domain

The script in Listing 5.43 binds to the root domain. Regardless of which domain the client is logged on to, the root domain
in the forest is returned.

Listing 5.43 Constructing an ADsPath to the Root Domain with rootDSE

1
Set objRootDSE = GetObject("LDAP://rootDSE")
2
3 strADsPath = "LDAP://" & objRootDSE.Get("rootDomainNamingContext")
Set objRootDomain = GetObject(strADsPath)

In any domain in the fabrikam.com forest, the strADsPath variable contains:


>LDAP://DC=fabrikam,DC=com

Binding to the Configuration Container

The script in Listing 5.44 binds to the configuration container in the forest.

Listing 5.44 Constructing an ADsPath to the Configuration Container with rootDSE

1
Set objRootDSE = GetObject("LDAP://rootDSE")
2
3 strADsPath = "LDAP://" & objRootDSE.Get("configurationNamingContext")
Set objConfiguration = GetObject(strADsPath)

In any domain in the fabrikam.com forest, the strADsPath variable contains:

LDAP://CN=Configuration,DC=fabrikam,DC=com

Binding to the Schema Container

The script in Listing 5.45 binds to the schema container in the forest.

Listing 5.45 Constructing an ADsPath to the Schema Container with rootDSE

1
Set objRootDSE = GetObject("LDAP://rootDSE")
2
3 strADsPath = "LDAP://" & objRootDSE.Get("schemaNamingContext")
Set objSchema = GetObject(strADsPath)

In any domain in the fabrikam.com forest, the strADsPath variable contains:

LDAP://CN=Schema,CN=Configuration,DC=fabrikam,DC=com

Note

• For a complete list of rootDSE properties, see the Active Directory Programmer's Guide link on the Web
Resources page at http://www.microsoft.com/windows/reskits/webresources.

Sending Keystrokes to a Program


Microsoft® Windows® 2000 Scripting Guide

By providing scripts with access to most COM objects, WSH enables you to automate applications that have a COM-based
object model. Unfortunately, some applications, especially older ones, do not have a COM-based object model. To
automate these applications, WSH provides a way to send keystrokes to these applications.

When you use the WshShell SendKeys method to send keystrokes to an application, your script mimics a human typing on
the keyboard. To send a single keyboard character, you pass SendKeys the character itself as a string argument. For
example, "x" to send the letter x. To send a space, send the string " ". This is exactly what a user would do if he or she
was working with the application: to type the letter x, the user would simply press the x key on the keyboard.

When you use the SendKeys method, special keys that do not have a direct text representation (for example, CTRL or ALT)
are represented by special characters. Table 3.16 lists these SendKeys representations for commonly used keys.

Table 3.16 SendKeys Representations of Common Keys


Key SendKeys Representation
BACKSPACE {BACKSPACE}, {BS}, or {BKSP}
BREAK {BREAK}
CAPS LOCK {CAPSLOCK}
DEL or DELETE {DELETE} or {DEL}
DOWN ARROW {DOWN}
END {END}
ENTER {ENTER} or ~
ESC {ESC}
HELP {HELP}
HOME {HOME}
INS or INSERT {INSERT} or {INS}
LEFT ARROW {LEFT}
NUM LOCK {NUMLOCK}
PAGE DOWN {PGDN}
PAGE UP {PGUP}
PRINT SCREEN {PRTSC}
RIGHT ARROW {RIGHT}
SCROLL LOCK {SCROLLLOCK}
TAB {TAB}
UP ARROW {UP}
SHIFT +

CONTROL ^

ALT %

BACKSPACE {BACKSPACE}, {BS}, or {BKSP}


All function keys, like F1, are represented by the button name contained within braces for example, {F1} for the F1 button
and {F2} for the F2 button.

For example, the following script starts Notepad and then types the sentence, "This is a test."

Set objShell = WScript.CreateObject("WScript.Shell")


objShell.Run "Notepad.exe"
Do Until Success = True
Success = objShell.AppActivate("Notepad")
Wscript.Sleep 1000
Loop
objShell.SendKeys "This is a test."

When the script runs, Notepad will open, and the sample sentence will be typed in, as shown in Figure 3.12.

Figure 3.12 Controlling Notepad by Using SendKeys


Note

• You can send repeated keystrokes by using the SendKeys method. For example, to send the letter a ten times,
you send the string "{a 10}". You must include a space between the keystroke and the number. SendKeys allows
you to send only repeated single keystrokes. You cannot send multiple characters using repeated keystrokes; for
example, this command will fail: {dog 10}.

You should be aware that sending keystrokes to an application is not the optimal method for automating a procedure. If
you have an application in your enterprise that you need to automate and it has no COM-based object model, you might
consider this technique. However, you should first examine whether other methods exist for automating that particular
application.

Although SendKeys can be used effectively, there are several potential problems with this approach:

• The script might have difficulty determining which window to send the keystrokes to.

• Because the application runs in GUI mode, a user might close the application prematurely. Unfortunately, this will
not terminate the script, and the script could end up sending keystrokes to the wrong application.

• The script might have difficulty synchronizing with the application.

This timing issue is especially troublesome, simply because scripts tend to run much faster than GUI applications. For
example, this simple script, which starts Calculator and then tries to type the number 2 into the application, is coded
correctly but will likely fail when run (Calculator will start, but the number 2 will not be entered):

Set objShell = WScript.CreateObject("WScript.Shell")


objShell.Run "Calc.exe"
objShell.AppActivate "Calculator"
objShell.SendKeys "2"

The script fails not because of a syntax issue but because of a timing issue. As quickly as it can, the script issues
commands to:

1. Start Calculator.

2. Switch the focus to Calculator (using the AppActivate method).

3. Send the number 2 to Calculator.

Unfortunately, the script runs faster than Calculator can load. As a result, the number 2 is sent, and the script terminates,
before Calculator can finish loading and start accepting keystrokes.

There are at least two ways of working around this problem. First, you might be able to estimate how long it will take an
application to load and then pause the script for that amount of time. For example, in this script the Run method is called,
and then the script pauses for 5 seconds, giving Calculator time to load:

Set objShell = WScript.CreateObject("WScript.Shell")


objShell.Run "Calc.exe"
Wscript.Sleep 5000
objShell.AppActivate "Calculator"
objShell.SendKeys "2"
Of course, is some cases it might be difficult to estimate how long it will take before an application is loaded and ready to
accept keystrokes. In that case, you can call the AppActivate method and check the return value.

Using AppActivate

Before sending keystrokes to an application, you must first ensure that the application is running and that the focus is on
the application (that is, the application is running in the active window). You can use the AppActivate method to set the
focus on an application. The AppActivate method brings the specified window to the foreground so that you can then start
using the WshShell SendKeys method to send keystrokes to the application.

The AppActivate method takes a single parameter that can be either a string containing the title of the application as it
appears in the title bar or the process ID of the application. The AppActivate method returns a Boolean value that indicates
whether the procedure call has been successful. If the value is False, AppActivate has failed, usually because it was unable
to find the application (possibly because that application had not finished loading).

You can place your script in a loop, periodically calling AppActivate until the return value is True. At that point, the
application is loaded and prepared to accept keystrokes.

For example, this script checks the return value for AppActivate. If this value is False, the script pauses for 1 second and
then checks the value again. This continues until the return value is True, meaning that the application is loaded and ready
for use. At that point, the script continues.

Set objShell = WScript.CreateObject("WScript.Shell")


objShell.Run "Calc.exe"
Do Until Success = True
Success = objShell.AppActivate("Calculator")
Wscript.Sleep 1000
Loop
objShell.SendKeys "2"

When the script is determining which application to activate, the given title is compared to the title of each window visible
on-screen. If no exact match exists, the AppActivate method sets the focus to the first window whose title begins with the
given text. If a window still cannot be found, the first window whose title string ends with the text is given the focus. The
partial matching with the leading and trailing text of title bars ensures that AppActivate works with applications, such as
Notepad, that display the name of the currently opened document on the title bar. (For example, when you first start
Notepad, the window title is Untitled - Notepad, not Notepad.)

This means that when setting the focus to the Calculator, you can use one of the following lines of code:

objShell.AppActivate "Calculator"
objShell.AppActivate "Calc"
objShell.AppActivate "C"

Of course, this shortcut method of referring to a window can cause problems. For example, suppose you use this line of
code:

objShell.AppActivate "Calc"

If you happen to be working on a Microsoft Word document named Calculations.doc, the keystrokes might be sent to the
Word document instead of Calculator.

The script in Listing 3.30 demonstrates a more practical use of the SendKeys method: It starts and sets focus to the
Microsoft Management Console (MMC) and then sends keystrokes that cause the Add/Remove Snap-in and Add
Standalone Snap-in dialog boxes to be displayed. The script automates the first part of the common task of constructing
custom MMC snap-in tools.

Listing 3.30 Sending Keystrokes to a GUI Application

1
2
3 Const iNormalFocus = 1
4
Set objShell = WScript.CreateObject("WScript.Shell")
5
6 objShell.Run "mmc.exe",iNormalFocus
7
8
9 Wscript.Sleep 300
10
11
objShell.AppActivate "Console1"
12
13 Wscript.Sleep 100
14 objShell.SendKeys "^m"
15
Wscript.Sleep 100
objShell.SendKeys "{TAB}"
Wscript.Sleep 100
objShell.SendKeys "{TAB}"
Wscript.Sleep 100
objShell.SendKeys "{ENTER}"

Top of page

Running Scripts on Remote Computers


Microsoft® Windows® 2000 Scripting Guide

The WshController object provides you with the ability to run scripts on remote computers. The WshController object has a
single method, CreateScript, which returns a WshRemote object.

In turn, the WshRemote object can then be used to run the worker script. The worker script is not run as a result of the
call to CreateScript. Instead, the WshRemote object Execute method is used to actually run the script on the remote
computer.

The script in Listing 3.42 runs the hypothetical worker script MapNetworkDrive.vbs on the remote computer, RASServer01.
Although the location of the worker script can be specified using either a local file path or a UNC path, because no path is
specified in Listing 3.42, this means the worker script must be located in the same directory as the controller script.

Listing 3.42 Running a Local Script on a Remote Computer

1
strRemoteComputer = "RASServer01"
2
3 strWorkerScript = "MapNetworkDrive.vbs"
4 Set objWshController = WScript.CreateObject("WshController")
5
6 Set objRemoteScript = _
7 objWshController.CreateScript(strWorkerScript, strRemoteComputer)
8
objRemoteScript.Execute
9
10
11 Do While Not objRemoteScript.Status = 2
Wscript.Sleep(100)
Wscript.Echo "Remote script not yet complete."
Loop

Note
• Remote access is not an interactive process, which means that remotely run scripts cannot display any GUI
elements on the remote computer. If you run a remote script that displays a GUI element, the script might fail or
produce indeterminate results. For example, suppose your script displays a message box that the user must
respond to. Because the script runs in a hidden window, the user will never be able to see, and thus never be
able to respond to, that message box. As a result, the script will hang, waiting for user input that will never be
provided.

Top of page

LDAP BIND: Establishing a Connection to the


Directory

Before accessing a directory service, we have to establish a technical connection with an object of the directory.
This could be a directory container (e.g. an organizational unit) or a single object.

Given that the technical access is accomplished via the LDAP protocol, we use the according LDAP notation as well:
Establishing a connection and logging on with respective logon information is called a Bind operation (has nothing
to do with the well-known DNS server software). Many aspects of Binding are described in MSDN: MSDN
Documentation of ADSI and BIND.

Unless otherwise mentioned, this topic describes bind operations always in Active Directory environments. The
ADSI Interface also permits bind operations on other directory services. Corresponding examples can be found in
the following topics.

Bind variations:

Bind using the user ID the script is run with

Bind using special credentials

Bind to the global catalog

Bind when the own domain name / forest is unknown

Bind as anonymous

Bind to an Exchange 5.5 Server

Bind as anonymous to Exchange 5.5

Bind to Novell eDirectory / NDS


Bind using the user ID the script is run with

This is the easiest way of connecting. You 'grab' the object for access by using a simple GetObject-Function. At
this, the ID of the user that runs the script is used automatically for authentication. This method can only be used
for accesses within the own forest, if possessing sufficient permissions. In addition, the appropriate notation of
the LDAP pathname needs to be considered (especially if commas or other special characters are used!)
Set obj = GetObject("LDAP://server.cerrotorre.de/cn=Philipp,ou=Accounts,dc=cerrotorre,dc=de")

WScript.Echo obj.name

After that, the object 'Philipp' of the OU 'Accounts' of the domain 'cerrotorre.de' can be accessed via the
variable obj. However, access to all objects of a container is also possible:
Set ou = GetObject("LDAP://server.cerrotorre.de/ou=Accounts,dc=cerrotorre,dc=de")

For Each obj In ou


WScript.Echo obj.name
Next

Serverless Binding:

Please keep in mind that the server name can be left out in the LDAP pathname - the station where the script runs
discovers a domain controller from the user's domain automatically (via DNS). A shortened LDAP pathname can be
used particularly when running the script directly on a domain controller:
Set ou = GetObject("LDAP://ou=Accounts,dc=cerrotorre,dc=de")

For Each obj In ou


WScript.Echo obj.name
Next

Serverless Binding should not be used if you develop for other directory services such as Lotus Notes LDAP or
eDirectory. You can not use serverless binding here.

< back to top

Bind using special credentials

The common method of binding to the directory always works when a logged on user wants to access objects of his
own domain respectively his own Active Directory forest. However, it might quite often be necessary to access a
directory service where you are not an currently authenticated user. In that case, the bind
variation OpenDSObject allows to pass the username and password and thus the logon to e.g. foreign forests is
possible.
Set dso = GetObject("LDAP:")
Set ou = dso.OpenDSObject("LDAP://controller.cerrotorre.de/ou=test,dc=cerrotorre,dc=de",
"administrator", "P@ssw0rd", 1)
For Each obj In ou
WScript.Echo obj.name
Next

In this example the OU object of the domain company.com is accessed by logging on the
server 'controller.domain.com' with the username 'administrator'and password 'P@ssw0rd'. The last parameter (1)
acts as a logon-flag, ensuring a secure Kerberos logon.

ADSI Reference in MSDN: OpenDSObject()

The username of an AD logon can be given in the following way:

Pure logon e.g. 'administrator', for this, the logon-flag needs to be set to
name '1' (secure logon)

NetBIOS
logon e.g. 'DOMAIN\administrator'
name

User
principal e.g. 'administrator@domain.com'
name

Distinguis e.g. 'cn=administrator,cn=users,dc=domain,dc=com', for


hed name this, the logon-flag needs to be set to '0' (clear text logon).

The logon flag determines the type of access. Important are the two values '0' (for encrypted logon in clear text)
and '1' (for secure logon via Kerberos or NTLM). Of course, a secure logon should be preferred to clear text logon.
However, situations may arise when an insecure clear text logon is needed. Especially when using a bind operation
to logon to other directory services like Novell eDirectory or OpenLDAP systems, the logon-flag must be set to '0'.
In order to avoid a disclosure of the password from the net, the use of LDAP-SSL is recommended - then the whole
traffic of the LDAP protocol is encrypted.

Microsoft explanations of the logon flag in MSDN

The server name can be left out in the LDAP pathname of Active Directory environments and it is automatically
bind to an accessible domain controller of the own domain. Also, username and password can be provided as NULL
string (''), then the logon data of the own user is used automatically. This possibility might be useless if using the
bind option for the logon to another forest DC - thus, server and logon data have to be indicated accordingly.
< back to top

Bind to the Global Catalog


When connecting to a domain controller by using ADSI, only data from the schema partition, the configuration
partition and the own domain can be provided. However, if you want to request objects of the whole forest from a
single domain controller, then you have to connect to a global catalog (GC). Such special domain controllers
provide objects from other domains via LDAP using the special TCP port 3268.

However, these objects can only be read and simply show some (the most important) attributes!

A technical option for the bind to a global catalog is to change the LDAP pathname so that the TCP port number
3268 is used. This is possible when using the function GetObject as well as OpenDSObject.
Set ou = GetObject("LDAP://server.cerrotorre.de:3268/ou=Accounts,dc=cerrotorre,dc=de")
For Each obj In ou
WScript.Echo obj.name
Next

Set ou = dso.OpenDSObject("LDAP://server.cerrotorre.de:3268/ou=Accounts,dc=cerrotorre,dc=de",
"administrator", "P@ssw0rd", 1)
For Each obj In ou
WScript.Echo obj.name
Next

Prerequisite, of course, is that the regarding server 'server.cerrotorre.de' has been set up as a global catalog.

Here's an easier option that utilizes a special form of the pathname, where the term 'LDAP' is simply replaced by
'GC'. So the special port number 3268 can be omitted:
Set ou = GetObject("GC://server.cerrotorre.de/ou=Benutzer,dc=firma,dc=de")
For Each obj In ou
WScript.Echo obj.name
Next

Set dso = GetObject("LDAP:")


Set ou = dso.OpenDSObject("GC://server.cerrotorre.de/ou=Accounts,dc=cerrotorre,dc=de",
"administrator", "P@ssw0rd", 1)
For Each obj In ou
WScript.Echo obj.name
Next

A Serverless Binding can be run also when you are in Active Directory environments. Then a global catalog will
automatically be searched by DNS:
Set ou = GetObject("GC://ou=Benutzer,dc=cerrotorre,dc=de")
For Each obj In ou
WScript.Echo obj.name
Next

< back to top

Bind without knowing the own Domain / Forest name

In many cases you want to develop scripts that run in different Active Directory environments. Think about a script
that e.g. displays any information about certain objects within the own domain or is responsible for specific
changes. In order that this script runs in any domains, you could let pass the domain name as parameter. But it is
more sophisticated to automatically identify the current domain name by querying the Active Directory itself
through severless binding.

The relevant information can be read in a special directory entry, available on every domain controller:
the rootDSE (Root Directory Service Entry).
You can read here the distinguished name of your own domain from the attribute 'defaultNamingContext' and
make an LDAP pathname right away with which the desired domain objects can be accessed.
Set rootDSE = GetObject("LDAP://rootDSE")
domainDN = rootDSE.Get("defaultNamingContext")

set domain = GetObject("LDAP://" & domainDN)


For Each obj In domain
WScript.Echo obj.name
Next

This script lists all objects directly in the main name context of an Active Directory domain - it's the container
where all 'normal' user and group objects are saved in. By the way, you can (given the relevant rights) access
the configuration container of the forest without knowing the accurate notation, because the respective DN is
documented as 'configurationNamingContext' attribute in the rootDSE.
Set rootDSE = GetObject("LDAP://rootDSE")
domainDN = rootDSE.Get("defaultConfigurationContext")

Set domain = GetObject("LDAP://" & domainDN)


For Each obj In domain
WScript.Echo obj.name
Next

< back to top

Bind as Anonymous

LDAP generally offers the possibility to logon to a directory without any user credentials. This is the so called
'anonymous bind'. Whether this anonymous bind is allowed or not depends on the type of directory service and the
current configuration. When an anonymous bind is possible, in most cases the access rights for anonymous LDAP
users are quite restricted.

If you want to logon to an Active Directory directory as an anonymous user without user name and password, you
have to distinguish between Windows 2000 forests and forests that operate on Windows 2003 or later.

AD under Windows 2000: The anonymous logon is allowed by default.

AD under Windows 2003 (and later): Initially, the anonymous access is limited
to the rootDSE entry (Root Directory Service Entry). Thus, you can readout a list
of naming contexts or the Active Directory version of the forest. But if trying an
anonymous access to normal objects and attributes of the forest, it has to be
allowed by a global switch first. This is the Active Directory attribute dsHeuristic.
This value is stored as an attribute of an directory object in the configuration
partition: CN=Directory Service,CN=Windows NT, CN=Services,CN=Configuration,
DC=root, DC=com. The default value is 0000000, a value of 0000002 enables the
anonymous access to the directory.
Don't forget: Which objects and attributes you are allowed to access is also determined by access standards
existing for the entries ANONYMOUS LOGON and Everyone in the relevant ACLs. The out-of-the-box setting
these entries have absolutely no access right to domain objects - even if an anonymous logon is generally allowed
by dsHeuristics.

There are some more things that need to be taken into consideration during a bind operation. An anonymous user
is unable to see the content of container objects. It is inevitable to access single objects like user, groups or
contacts by using the complete LDAP path. For this, the logon with the function OpenDSObject, but without user
name and password, are used:
Set dso = GetObject("LDAP:")
Set mbx =
dso.OpenDSObject("LDAP://dc1.cerrotorre.de/cn=PhilippF,ou=Consultants,dc=cerrotorre,dc=de", "",
"", 0)
WScript.Echo obj.name
WScript.Echo obj.mail

If you want to access several objects or if you don't know the precice LDAP paths, than you may run a directory
search via ADO interface. The procedure of an ADO search is explained in the SelfADSI Tutorial in the topic
'Searching for objects in the directory'.

In order to run an anonymous ADO query within an Active Directory, some modifications need to be accomplished.
First of all, the base DN string of the directory search is to be omitted - as an anonymous user you are unable to
'see' a directory container.

Secondly, you have to use the global catalog provider for the search, because it only allows a search without
defined base string. The search starts directly with the following LDAP path:

<GC://Server>

Here is an example in which all user objects are displayed. To access other objects you just have to change
the LDAP-Filter:
Set ado = CreateObject("ADODB.Connection") 'Creation of the ADO connection
ado.Provider = "ADSDSOObject"
ado.Properties("User ID") = "" 'no credentials!
ado.Properties("Password") = ""
ado.Properties("Encrypt Password") = False
ado.Open "AD-Anon-Search" 'this is a arbitrarily chosen name

serverName = "nadrash.cerrotorre.de" 'replace this with your own server


name
filterStr = "(&(objectCategory=person)(objectClass=user))" 'search for user objects

Set objectList = ado.Execute("<GC://" & serverName & ">;" & filterStr & ";ADsPath;SubTree")

While Not objectList.EOF


WScript.Echo objectList.Fields(0).Value
objectList.MoveNext 'next foudn object
Wend

Please note that an ADO search to the Global Catalog returns the corresponding LDAP pathname of the whole
forest (because we asked for the attribute 'ADSPath' ...). The returned LDAP pathnames of the Global Catalog are
displayed with the protocol answer 'GC://', as you can see in the above script example:
You will neither be able to read all attributes nor to change / rewrite them during a following connect to these
pathnames - because you are accessing the Global Catalog! Get more information about the handling of search
results of the Global Catalog under the topic 'The Global Catalog' here in the SelfADSI Tutorial.

< back to top

Bind to Novell eDirectory / NDS Server

If you want to bind to an Exchange 5.5 server in order to access mailbox information or the set up of the mail
organization, some things will need to be considered.

First of all, it's important to bear in mind that a LDAP pathname of a Novell eDirectory is different to other Active
Directories: Instead of a domain (e.g. ...,dc=cerrotorre,dc=de), the superior hierarchy of such a directory is
comprised of an organization (...,o=...) or country object (...,c=...).

cn=PFoeckel,ou=Karlsruhe,o=CerroTorre
cn=BierSan,ou=Students,ou=Sydney,c=au

When binding, you always have to use the function OpenDSObject and directly name the correspondent Novell
server (and, if applicable, the LDAP port number the server is set up with). Username is the complete LDAP
pathname of the user that is to be logged on. Logon flag is always 0:
Set dso = GetObject("LDAP:")
Set recipients = dso.OpenDSObject("LDAP://nov-ldap.cerrotorre.de/ou=Karlsruhe,o=CerroTorre", _
"cn=PFoeckel,ou=Karlsruhe,o=CerroTorre", "P@ssw0rd", 0 )

For Each obj In recipients


WScript.Echo obj.name
Next

The logon via unencrypted password is quite unsecure, but if the server provides the appropriate SSL certificate
settings, you could use LDAP-SSL on TCP-Port 636. Then, the whole LDAP Communication and thus username and
password as well will be encrypted via a SSL tunnel.

If the logon to the eDirectory shall be anonymous, an empty string is passed over instead of username und
password. Novell server allow anonymous logon in general, but then you have got only access where the entry
[public] is existing as trustee:
Set dso = GetObject("LDAP:")
Set recipients = dso.OpenDSObject("LDAP://nov-ldap.cerrotorre.de/ou=Karlsruhe,o=CerroTorre", "",
"", 1)

For Each obj In recipients


WScript.Echo obj.name
Next

< back o top

Bind to an Exchange 5.5 Server

If you want to connect to an Exchange 5.5 server in order to access mailbox information or configuration of the
mail organization, you have to take some things into consideration.

You need to keep in mind that LDAP pathnames of Exchange 5.5 directories slightly differ from the 'normal' AD
syntax: In an organization with the notation 'Company-Mail', the receiving container in the site 'Karlsruhe' would
have the following pathname:

cn=Recipients,ou=Karlsruhe,o=Company-Mail

Moreover, you always have to work with OpenDSObject when doing a bind operation and state the relevant
Exchange server at the same time (and, if applicable, the LDAP port number with which the server is set up with,
too). The best user name is the NetBIOS logon name of a user with pertinent credentials in the Exchange directory.
'1' has to be used as logon flag:
Set dso = GetObject("LDAP:")
Set recipients = dso.OpenDSObject("LDAP://ex55.cerrotorre.de/cn=Recipients,ou=Karlsruhe,o=Firma-
Mail", _
"NTDOMAIN\administrator", "P@ssw0rd", 1)

For Each obj In recipients


WScript.Echo obj.name
Next

Furthermore, Exchange 5.5 as LDAP server shows an annoying habit: It makes it difficult to access objects not
displayed in the address book. This can be avoided by using a special version of the logon name in the operation
OpenDSObject:

cn=<username>, dc=<domain>, cn=admin

By the use of this administrative bind logon, it is possible to access hidden or even deleted (still in the DIR data
base) objects besides normal ones.

Hidden objects are objects where the LDAP attribute Hide-From-Address-Book is set TRUE.
Deleted objects are objects where the LDAP attribute Is-Deleted is set TRUE.

An example for such an access:


Set dso = GetObject("LDAP:")
Set recipients = dso.OpenDSObject("LDAP://ex55.cerrotorre.de/cn=Recipients,ou=Karlsruhe,o=Corp-
Mail", _
"cn=administrator,dc=cerrotorre,cn=admin", "P@ssw0rd", 0 )

For Each obj In recipients


WScript.Echo obj.name
Next

Please note that the logon needs to be done with the authentication flag '0' (for simple auth with cleartext
password).
< back to top
Bind as Anonymous to Exchange 5.5 Server

If you want to connect to an Exchange 5.5 server as an anonymous user without user name and password, this
needs to be allowed explicitly at the relevant server or the corresponding Exchange 5.5 site at first:

From now on, a client trying a bind operation with empty password and user name is logged on as an anonymous
user and has access to directory information - however, only those that are enabled for an anonymous access. On
which attributes an anonymous logged on LDAP client is allowed to access can be seen and changed in the DS site
configuration of the accordant Exchange 5.5 location.
However, there are some things that need to be taken into consideration during bind operations. An anonymous
user is unable to see the content of container objects. Thus, it is inevitable to access single objects like mailboxes,
custom recipients or distribution list by the use of the complete LDAP path. For this, the logon with the
operation OpenDSObject but without user name and password is used:
Set dso = GetObject("LDAP:")
Set mbx =
dso.OpenDSObject("LDAP://ex55.cerrotorre.de/cn=PhilippF,cn=Recipients,ou=Karlsruhe,o=Corp-Mail",
_
"", "", 0)

WScript.Echo obj.name
WScript.Echo obj.mail

If you want to access several objects or if you don't know the precise LDAP paths, than you may run a directory
search via ADO interface. The procedure of an ADO search is explained in the SelfADSI Tutorial under the
paragraph, 'Searching objects in the directory'. But in order to run an anonymous ADO inquiry against an
Exchange 5.5 server, some modifications need to be accomplished. They are explained in the Microsoft knowledge
base articleQ223049. First of all, the base string of the directory search is left out and secondly, the Global Catalog
Provider with the LDAP port 389 (or the set up LDAP port of the relevant server) has to be stated in the LDAP
pathname. Otherwise, this provider is useless for accesses to Exchange 5.5 directories, because only Active
Directory directories do feature a Global Catalog operation. However, in this case here we use this trick in order to
run an anonymous ADO search.

A third change compared to a common ADO search within the directory is the explicit creation of an
ADODB.Command object, because its characteristic PageSize is needed for the anonymous query. In the following
example all mailbox objects are indicated. For accessing other objects you just have to change the LDA filter:
Set dso = GetObject("LDAP:") 'for accessing via LDAP

Set ado = CreateObject("ADODB.Connection") 'creation of the ADO connection


ado.Provider = "ADSDSOObject"
ado.Properties("User ID") = "" 'no logon data !
ado.Properties("Password") = ""
ado.Properties("Encrypt Password") = False
ado.Open "EX55-Anon-Search" 'this is a arbitrarily chosen name
serverName = "kailash.cerrotorre.de" 'replace the own server name here
filterStr = "((objectClass=organizationalPerson))" 'LDAP search filter for mailboxes

Set cmo = CreateObject("ADODB.Command") 'Creation of the ADO connection


cmo.ActiveConnection = ado
cmo.CommandText = "<GC://" & serverName & ":389">;" & filterStr & ";ADsPath;SubTree"
cmo.Properties("Page Size") = 99

Set objectList = cmo.Execute 'processing the search

While Not objectList.EOF 'anonymous and direct bind to the object


Set mbx = dso.OpenDSObject(objectList.Fields(0).Value, "", "", 0)

WScript.Echo mbx.name

objectList.MoveNext 'next element


Wend

Das könnte Ihnen auch gefallen