Editor's note: This article is the ninth part of a 12-part series about Active Directory Service Interfaces (ADSI). The series started in the January 1999 issue. Refer to previous installments for definitions and background information.
For the past 2 months, I've shown you how to use ADSI to manipulate persistent and dynamic objects such as services, shares, sessions, and resources. This month, I conclude the discussion of these types of objects by looking at the archetypal entries in this area: printer queues and print jobs. I'm going to show you how to
- Identify print queues in the Windows 2000 (Win2K) Active Directory (AD)
- Bind to a print queue and access its properties
- List the print jobs in a print queue and manipulate them
The scripts that I provide use the WinNT: provider. Thus, they work not only on Win2K systems but also on Windows NT systems. However, you need to adapt the code for two of the scripts. For more information about this adaptation, see the sidebar "How to Adapt IDPrintQueue.vbs and BindPrintQueue.vbs for NT Systems," page 10.
Using ADO to Search the AD Store
In the article "An ADSI Primer, Part 5: Using ADO to Script Fast ADSI Searches," May 1999, I showed you how to use an ActiveX Data Object (ADO) query to quickly search for and display the ADsPaths of users in the AD store. You can conduct a similar search for printer objects. To make this search easy, I created the SearchAD function.
As Listing 1, page 10, shows, the SearchAD function takes three parameters. The first parameter (strLDAPBase) is the root you want to search from. You must specify the full Lightweight Directory Access Protocol (LDAP) path. The second parameter (strCriteria) is the set of ADO criteria that defines what you're searching for. The third parameter (strDepth) is the depth of the search. You can specify one of three depths: Base, OneLevel, or SubTree.
If the search function finds items that match the criteria, it returns a result of True with a multidimensional array (arrADsPaths) containing the items. If the search function doesn't find any items that match the criteria, it returns the result of False and leaves arrADsPaths undefined.
The array is multidimensional to hold both the ADsPath and the common name (CN) properties of the printer objects it returns. For each entry returned, the first array element, array(x,0), is the AdsPath and the second array element, array(x,1), is the CN property. The first array element has the value of 0 and the second element has the value of 1 because array element indexes start at 0. (For more information about multidimensional arrays, see Dino Esposito, "Understanding VBScript," July 1999.) You can easily extend the SearchAD function to take in a list of y properties and return an array(x,y).
To use the SearchAD function, you must include the function code in Listing 1 in your script. Let's look at some examples of what you can use this function for.
Identifying Print Queues
Suppose you need to search the AD store for objects of class printQueue. You can create a script, IDPrintQueue.vbs, that not only uses the SearchAD function to find these objects but also writes their ADsPath and CN properties to a temporary file, displays the file in Notepad, and erases the file when you close Notepad. Listing 2 contains the code you add before the SearchAD function to create IDPrintQueue.vbs. (You can find the entire script on the Win32 Scripting Journal Web site.)
IDPrintQueue.vbs uses several constants. The constant strDomainToSearch specifies the AD path you want to start the search from. The constant vbMaximizedFocus maximizes the Notepad screen when that application starts. The constant TEMPFILE sets the location of the temporary text file, and the constant ForWriting opens that file and starts writing from the beginning of it.
The code for opening and closing the text file and displaying that file in Notepad might look familiar because I've used the code in previous articles. This code uses an If...Else...Then statement to first open a temporary text file and then write the ADsPaths and CNs in it. (If the text file already exists, the script overwrites it.) Next, the code sets the third parameter of the Shell::Run method to True, so that this text file opens in Notepad with its screen maximized. IDPrintQueue.vbs stops executing until you close Notepad, which places an integer return code into the intRC variable. (When a program closes, it typically returns an integer value of 0 to specify a successful closure or another value specifying an error.) When Notepad exits, the script deletes the text file.
Screen 1, page 12, shows an example of IDPrintQueue's output. To make this output easier to read, I printed the CN first and put the ADsPath on the next indented line. The output consists of three printQueue objects. The first object's CN is DC1-ph_stores_hp4000. Its ADsPath is LDAP://CN=DC1-ph_stores_hp4000,CN=DC1, OU=DomainControllers,DC=mycorp,DC=com.
Binding to Print Queues
With the printQueue objects identified, suppose you want to connect to DC1-ph_stores_hp4000 and list its queued jobs. Unfortunately, you can't simply connect to this AD object and print the jobs because you must use the WinNT: provider to connect to printer objects—and the SearchAD function identifies only the LDAP: provider. Thus, you need to manipulate the data that the function returns into the WinNT: path.
You can modify Listing 2 so that it not only manipulates the data but also uses the resulting WinNT: path to bind to the object and print its properties. The modification involves adding a constant and the code in Listing 3. (The Win32 Scripting Journal Web site contains a script, BindPrintQueue.vbs, that incorporates this modification.)
Adding the constant. You need to add the line
after the On Error Resume Next statement in Listing 2. The strDomainOrWorkGroup constant specifies the domain or workgroup in which the servers or workstations reside.
Adding the code in Listing 3. The code in Listing 3 extracts the needed data (i.e., the computer name and the printer name) from the SearchAD function's results (i.e., the printQueue object's ADsPath and CN) and puts that data into the WinNT: path. The code then uses the WinNT: path to bind to the printQueue object and print its properties. Callout A in Listing 2 specifies where to place this code.
Here's how the code in Listing 3 works. To extract the computer name, the code retrieves the ADsPath from the first array element (LDAP://CN=DC1-ph_stores_hp4000,CN=DC1, OU=Domain Controllers,DC=mycorp, DC=com) and uses a comma delimiter to split it into separate strings. The code retrieves the second string from that split (CN=DC1) and adds it to the strComputer string variable. Ignoring the string's first three characters (CN=), the code places the remaining characters (DC1) back into strComputer.
To get the printer name, the code retrieves the CN from the second array element (DC1-ph_stores_hp4000). Ignoring the first x + 1 characters (where x is the length of the computer name), the code places the remaining characters (ph_stores_hp4000) in the strPrinter string variable.
With the needed data extracted, the code assembles the strings into the WinNT: path (i.e., WinNT://MYCORP/DC1/ph_stores_hp4000). The code then uses that path to bind to the printQueue object. Finally, the code prints that object's five properties (IADs::Name, IADsPrintQueueOperations::Status, IADsPrintQueue::Model, IADsPrintQueue::Location, IADsPrintQueue::PrinterPath) to confirm that the printer exists.
Manipulating Print Queues and Print Jobs
Having successfully connected to the printQueue object, you can use the IADsPrintQueueOperations interface to its full extent. This interface's methods correspond to the specific print queue functions with which you're probably familiar (e.g., pause, resume, purge). This interface also offers two other useful features: the IADsPrintQueueOperations::Status property method and the IADsPrintQueueOperations::PrintJobs method. (For more information about all the methods and property methods mentioned in this article, see the sidebar "A Word About the Interfaces.")
IADsPrintQueueOperations::Status. This property method lets you query the status of printers. Although the code in Listing 3 prints the Status property of a printQueue object, the value that the code returns is an integer (e.g., 1, 2). Unless you know what status the integer represents (e.g., paused, pending deletion), the information is of little use.
You can use the Status property method to remedy this situation because it has a defined set of constants. If you specify these constants, you can use the Status property method with a Select Case statement and the MsgBox function to print a text message specifying the printer's status. So, for example, instead of getting the value of 1, you get the message Paused. (The Win32 Scripting Journal Web site contains a script, PrintQueueStatus.vbs, that you can use to produce print queue status messages.)
IADsPrintQueueOperations::PrintJobs. The PrintJobs method lets you obtain a collection object representing print jobs. As a result, you can use three other types of interfaces.
Because the PrintJobs method obtains an object that is a collection, you can use the IADsCollection interface. So, for example, you can use the IADsCollection::Add and IADsCollection::Remove methods to add and remove print jobs from the collection.
Because the collection object is holding print jobs, you can use the IADsPrintJobs and IADsPrintJobOperations interfaces. You can use IADsPrintJobs property methods to obtain information about a print job. For example, you can use the IADsPrintJob::TotalPages property method to see the total number of pages a print job contains and the IADsPrintJob::Size property method to see the size of the print job in bytes.
The IADsPrintJobOperations interface offers methods such as Pause, which lets you suspend the processing of print jobs in a print queue. And like the IADsPrintQueueOperations interface, IADsPrintJobOperations has a Status property method with a defined set of constants that you can use to print text messages about a print job's status. (The Win32 Scripting Journal Web site contains a script, PrintJobStatus.vbs, that you can use to produce print job status messages.)
One important note about IADsPrintJobOperations is that its Position property method is a read/write value. As a result, you can use this property to move jobs around in the print queue. Several IADsPrintJob property methods are also read/write, including StartTime, UntilTime, Priority, Description, Notify, and NotifyPath.
This month's discussion about how to access and manipulate print queues and print jobs concludes the look at ADSI's persistent and dynamic object interfaces. Next month, I'll delve into a new area: scripting permissions and security in the Win2K AD.
This article is adapted from Alistair G. Lowe-Norris' forthcoming book about the Windows 2000 Active Directory (O'Reilly and Associates).