Access and manage user accounts and network resources, no matter what network environment they come from

Do you want to use scripting or Visual Basic (VB) to enhance your user administration and network resource management? Would you like to use a C compiler to create utilities that work without modification on both Windows NT and NetWare? Do you want to add 200 user accounts with proper settings in a batch run or print a customized report of your users?

In February, Microsoft released a specification that makes these tasks possible: Active Directory Service Interfaces (ADSI) 1.0. ADSI is not a multivendor or Internet Engineering Task Force (IETF) standard; the copyright belongs solely to Microsoft. With ADSI, you can manage the resources in your directory services--and it doesn't matter which network environments those resources come from.

ADSI works with true directory services, such as NetWare 4.x's Novell Directory Services (NDS) and NT 5.0's Active Directory (AD). ADSI also works with network environments that don't have a directory service, such as NetWare 3.x (instead, its Bindery stores user accounts and other objects) and NT 4.0 (instead, its Security Accounts Manager--SAM--stores the user database and domain models). Of course, you need an ADSI provider for all these environments.

When you have a true directory service, you can create directory-enabled applications with ADSI, whether you are an inhouse developer or independent software vendor (ISV). These applications go beyond network administration. They use the directory service as a distributed information store to add value to current networked applications.

How does ADSI work? NT, NetWare, and other network operating systems have native APIs for accessing and managing network resources. ADSI just puts a uniform layer on top of the native APIs so that you don't need to use different software development kits (SDKs) or learn different APIs to program for multiple network environments. ADSI abstracts the objects and interfaces of the underlying directory services and creates component object model (COM) objects and interfaces for you to use.

Using ADSI might sound difficult, but it's not. You are probably already familiar with part of ADSI's technology: COM. ADSI uses the same COM technology as distributed component object model (DCOM) and ActiveX components. You just need to learn about those technological areas that you might not be too familiar with: the ADSI environment and ADSI objects.

The ADSI Environment
Both the ADSI application and provider run on your workstation. The target server does not need any ADSI support or installation. The server just receives native calls. The main platform for the 32-bit ADSI program is currently NT 4.0, although ADSI also supports Windows 95, as Figure 1 shows. ADSI talks to four different providers: ADSNW.DLL for NetWare 3.x, ADSNDS.DLL for NetWare 4.x, ADSNT.DLL for NT 4.0, and ADSLDP.DLL for NT 5.0 and Lightweight Directory Access Protocol (LDAP) 2.0. These providers convert ADSI calls to Win32 API, NetWare, or LDAP calls.

Although you can use ADSI with different networks, it has the closest relationship with NT 5.0's AD. ADSI's and AD's terminology, design, structure, and name are similar. ADSI will be the primary interface for programming to AD; Messaging API (MAPI) and the traditional C language API for LDAP will be secondary.

You can use VB 4.0 (32-bit version), VB 5.0, Visual C++ 4.2, and Visual J++ with the Java Virtual Machine (JVM) to develop applications. According to Microsoft, you can also use any other application development tools that bind and invoke interfaces in COM objects or act as an Object Linking and Embedding (OLE) automation controller. For example, you can use ADSI with NT 5.0 Windows Scripting Host (WSH) to develop Visual Basic Script (VBScript) batches or scripts (see the sidebar "Use ADSI with WSH," page 164).

ADSI's Object Architecture
You won't find ADSI's object architecture complicated, but you might find it confusing because every element in the network directory service is referred to as an object. The object referral process begins when the network directory service abstracts its resources by creating objects to represent them. So, for example, users, servers, and printers become objects in the directory service (NDS or AD). ADSI, in turn, abstracts these NDS and AD objects into COM objects, as shown in Figure 2.

AD COM objects include dependent objects. Dependent objects are COM objects that represent common functions, such as collection handling. Because you can access dependent objects only through their host AD objects, I will not discuss them further.

AD COM objects represent elements in the underlying directory service. Two types exist: AD leaf objects and AD container objects. If an object can contain another object--just like an electronic folder can contain an electronic file--the object is an AD container object (herein referred to as simply container). If an object cannot house another object--just like a file cannot contain a folder--the object is an AD leaf object (or just leaf). Simply put, containers can house leafs, but leafs cannot house containers. Table 1 contains ADSI standard containers and leafs.

A container isn't limited to holding leafs. Just like an electronic folder can contain other folders, a container can hold other containers. For example, containers house AD Schema containers, which play an important role in ADSI. An AD Schema container holds the objects that define the schema for a particular part of a directory service. This container houses three different types of objects: AD Schema class objects, AD Property objects, and AD Syntax objects.

AD Schema class objects represent the different types, or classes, of elements in a directory service. One AD Schema class object exists for each type, such as user, computer, group, and organization. The AD Schema class object tells which properties are mandatory and which are optional for the corresponding object type. For example, the AD Schema class object for user might have a mandatory property of user name and an optional property of fax number. The AD Schema class object also tells whether the object's class is derived from other classes (and thus would support also their properties).

The AD Property object represents one property of the AD Schema class object. Thus, in this example, you need two AD Property objects: one to represent the user name and the other to represent the fax number. If two AD Schema class objects have the same property, they share the AD Property object. For example, if the AD Schema class objects of user and organization both have the property of fax number, only one AD Property object of fax number will exist.

Each property uses a syntax, which is represented by the AD Syntax object. So, in this example, you need two AD Syntax objects: one to represent the string syntax of the name property and another to represent the fax number syntax of the fax number property.

The AD Schema class objects define where containers and leafs belong. A given namespace permits only certain types of containers and certain types of leafs. Similarly, each type of container permits only certain types of containers and leafs. Thus, the schema are the rules of the directory service database because they define what information the database can store.

The schema in NT 5.0's AD and NetWare 4.0's NDS are extensible. You can define new object classes or redefine existing object classes. Applications are numerous, but one traditional example is to add payroll information to user objects.

NT 4.0 and NetWare 3.0, however, have locked schema. With fixed object classes, only the directory service provider (e.g., Microsoft and Novell) has the ability to add objects that are not in the standard ADSI object set.

It's Time to Start
Now that you know about ADSI's environment and object architecture, you can start experimenting with ADSI. But first, you need to download it from http://www.microsoft.com/win32dev/netwrk/adsi.htm. To create programs or scripts with ADSI, you need the several-megabyte SDK, which includes the ADSI specification (a 100-page Word document). Then you need the 500KB-compressed runtime libraries and possibly a patch for them. You must install these libraries in each workstation that will execute ADSI applications. (NT 5.0 will include these runtime libraries.)

After you install the downloaded files, you need to enable VB to use ADSI. In VB 5.0, simply select Project/References and check Active DS Type Library in the list of references. In VB 4.0, you first need to use the Tools menu to add the type library ActiveDS.Tlb (in System32 folder) to your Project menu. These steps let you use AD COM objects in your application.

For the sake of simplicity, the examples from this point on will focus on how to implement ADSI on NT rather than NetWare. The examples will deal mostly with users as the objects, but the same principles apply if the objects are printers, services, or other elements.

Browse a Little, Report a Lot
Once you have installed the necessary files, you can browse with DSBrowse, which is in the SDK. This sample application browses your namespaces and shows objects and properties in them.

Next, you can run several reports that will help you learn about your directory services. The reports that are most useful are the namespaces, user, and property reports.

Namespaces correspond to the four providers: WinNT, NWCOMPAT, NDS, and LDAP. Table 2 (page 166) gives examples of names in different namespaces. To check which namespaces are installed in your computer system, you can use this code:

Dim NamespacesObj as IADs Namespaces

Dim obj as IADs

Set NamespacesObj = GetObject("ADS:")

For Each obj in NamespacesObj

Debug.Print obj.Name

Next obj

This exercise not only tells you which namespaces are available, but also shows you many of the steps in ADSI programming. First, you define the variables with Dim statements, usually including the letters IADs. Next you use GetObject to instantiate (or create) the object based on the path given. GetObject is an ADSI helper function and is not to be confused with a VB function with the same name. Then on the same line, you assign the object to a variable, after which you can finally use it. If your object has many elements, you can walk through them with the For Each loop.

If you want to make a report containing all users and their home directory, you first need to use the code just given to find out the namespaces. (If you want, you can skip this step and just assume that you are using NT with the WinNT: namespace. This assumption isn't too risky.) Next, determine which domains you have. If your namespace is only WinNT:, you can get a list of the domains from your network neighborhood. Once you know the domains, use this code:

Dim Container As IADsContainer

Dim Child As IADs

Set Container = GetObject
("WinNT://SomeDomain")

Container.Filter = Array("user")

For Each Child In Container

Debug.Print Child.Name + Chr$(9) + Child.HomeDirectory

Next Child

This code sets a filter to the container so that it lists only users. It ignores other objects, such as groups and computers. (You can, however, run reports on other objects in a domain. The SDK can help you with this task.) The code then uses a For Each loop to recall each user's name and home directory.

A property report will tell you which optional properties each user supports. (A printout of mandatory properties would be empty.) Here's how to run the optional properties report:

Dim Class As IADsClass

Set Class = GetObject("WinNT://SomeDomain/Schema/User")

l = LBound(Class.OptionalProperties)

u = UBound(Class.OptionalProperties)

For i = l To u

Debug.Print Class.OptionalProperties(i)

Next i

Table 3 shows sample output from this procedure.

Another way you can access the properties of AD objects is to use the Get and Put methods. A benefit of using Get and Put is that, theoretically, you do not need to know anything about your network objects or properties beforehand. You can browse the schema and then use the property names found as variables in the Get and Put statements. (For more information on Get and Put, see the ADSI specification.)

NT 4.0 has some shortcomings with regard to user properties. It does not report three properties (PasswordExpirationDate, AccountDisabled, and IsAccountLocked) in OptionalProperties, so you cannot use them with Get and Put. Conversely, two properties (PasswordExpired and BadLoginCount) work only with Get and Put and not the previous procedure. Thus, you might have to use both approaches.

Another shortcoming is that you can access the properties of UserCannotChangePassword, PasswordNeverExpires, and Global/Local account type only through the UserFlags bit field property. So you have to find the right bits and do some calculations. Finally, you cannot access the dial-in settings and the properties LogonHours, HomeDirDriveLetter, PasswordLastChanged, and LastFailedLogin.

Manipulating Objects
When you have done enough browsing and reporting, you will likely be eager to make some changes. When manipulating objects, you need to identify both the objects and their paths. To identify the object from its path, you can use the GetObject function as in the code examples here. To identify the path to an object, you can use the ADsPath property by typing:

PathToSomeObj = SomeObj.ADsPath.

You can manipulate objects in many ways using Create, Delete, Move, and Copy. Here's an example of how to use Create to add a new user and its properties to a container in NT 4.0:

Dim Container As IADsContainer

Dim NewUser As IADsUser

Set Container = GetObject
("WinNT://SomeDomain")

Set NewUser = Container.Create
("user", "Maggie")

NewUser.FullName = "Henderson Maggie"

NewUser.HomeDirectory = "\\Server2\Maggie"

NewUser.SetInfo

NewUser.SetPassword ("secret")

Set NewUser = Nothing

An important element in this code is SetInfo. After you specify the object you are creating, its name, and its properties (lines 3 through 6 in the code), the client computer caches this information. The computer creates the object and adds the property values to the user database only when you use SetInfo (line 7). You do not have to use SetInfo, however, when creating a password because SetPassword (line 8) is a method and not a property.

Another important element is the Set NewUser = Nothingstatement (line 9). Use this statement when you finish working with a COM object. Otherwise, depending on the scope of the object variable, you might not release all the memory back to the operating system.

NT 5.0 beta includes a VBScript example program, which adds and deletes users using a Microsoft Excel worksheet. The program uses ADSI and is 170 lines long, half of which are comment lines.

Deleting, moving, and copying objects in ADSI is as simple as creating them. The ADSI specification can show you how to perform these and other procedures. If you have questions, Microsoft has an ADSI news group at msnews.microsoft.com/microsoft.public.
active.directory.interfaces. In addition, Microsoft's Knowledge Base will likely contain program examples and other information. You just need to go to http://
www.microsoft.com/kb and search on ADSI. The Microsoft Developer Network (MSDN) is another resource to tap into.

The Best Is Yet to Come
Although the ADSI specification is version 1.0, it performs more like a beta version. Using ADSI with NT 4.0 or NetWare is more limiting, although easier, than using the corresponding native APIs.

This situation, however, will change next year for two reasons. First, Novell will release an ADSI provider for NDS that will likely support the NetWare environment better than Microsoft's ADSI provider. Novell's ADSI provider will give NetWare users a way to access NDS via COM programming. This access will be beneficial because the clients will already be using 32-bit Windows.

Second, Microsoft will release NT 5.0 next year. ADSI is the chosen interface for NT 5.0's AD, so ADSI will perform at full capacity. In addition, although Microsoft designed ADSI and AD at the same time, it released ADSI earlier. The earlier release will give ADSI time to mature. By the time Microsoft releases NT 5.0, ADSI's bugs will likely be worked out.

Microsoft has committed to using LDAP 3 in NT 5.0 if the IETF finalizes this revised protocol in time. The LDAP 3 draft specification calls for an improved referral process, better support for user authentication, extensibility, and other improvements. (For more information about LDAP 3 and how various vendors plan to use it, see Craig Zacker, "LDAP and the Future of Directory Services, Part 2," page 191.) The use of LDAP 3 in NT 5.0 would likely bring about two changes: ADSI would get an LDAP 3 provider and LDAP 3 would update ADSI.

If AD dominates the industry, ADSI will be beside it. But if a new programming technique replaces object-oriented COM, ADSI will vanish. However, ADSI probably won't disappear in this millennium, so you need to take a closer look at it. ADSI is an object that represents the future.

Active Directory Service Interfaces (ADSI) 1.0
Contact: Microsoft * 425-882-8080
Web: http://www.microsoft.com
Price: Free