How to manage public folders
Exchange Server 2003 provides five new Windows Management Instrumentation (WMI) providers and 15 new WMI classes. As I showed you in "Managing Exchange 2003 with WMI, Part 1," January 2004, http://www.winnetmag.com/microsoftexchangeoutlook, InstantDoc ID 40755, these new providers and classes let you easily manage Exchange servers, logons, and mailboxes. The new providers and classes also let you easily manage Exchange public folders—a welcomed addition. All earlier versions of Exchange lack easy-to-use programmable capabilities for managing public folders. Although Collaboration Data Objects for Exchange Management (CDOEXM) and the Exchange OLEDB provider (through ADO) offer some public folder management capabilities, most Exchange administrators and programmers find CDOEXM and the Exchange OLEDB provider difficult to use.
The two WMI classes related to public folder management are Exchange_FolderTree and Exchange_PublicFolder. The WMI provider ExchangeFolderTreeProvider supports the Exchange_FolderTree class, which represents the public folder hierarchies available on the Exchange 2003 server to which you're connected. This class exposes a set of read-only properties and no methods. Therefore, this class only retrieves information about public folder hierarchies.
The WMI provider ExchangePublicFolderProvider supports the Exchange_PublicFolder class, which represents instances of all public folders across all existing public folder hierarchies available on the Exchange 2003 server to which you're connected. Note that this WMI provider doesn't support system public folders, such as Schedule+ Free/Busy. The Exchange_PublicFolder class exposes several methods and many read/write properties that let you manage public folders. Because the class exposes so many properties, I won't cover them all here. However, the scripting technique you use for most of the properties is similar; only the property name and parameters change.
Let's look at how to use the Exchange_FolderTree and Exchange_PublicFolder classes to perform several common public folder management tasks. Specifically, let's look at how to view public folder hierarchies, update a public folder's administrative note and replication schedule, create and delete public folders, and perform other public folder operations.
Viewing Public Folder Hierarchies
In "Exchange 2000 SP2 WMI Updates," January 2003, http://www.winnetmag.com/microsoftexchangeoutlook, InstantDoc ID 27211, I presented a script named GetCollectionOfInstances.wsf that you can use to list all instances of a WMI class. You can download GetCollectionOfInstances.wsf and all the other scripts I discuss in this article from the Exchange & Outlook Administrator Web site. Go to http://www.winnetmag.com/microsoftexchangeoutlook, enter InstantDoc ID 27211 in the InstantDoc ID text box, then click Download the Code. To run these scripts, you must have administrative privileges to the Exchange system. You must also have either administrative privileges (if you're accessing the namespace remotely) or user privileges (if you're accessing the namespace locally) to the Windows system. If you're using user privileges, make sure you can locally log on to the server.
GetCollectionOfInstances.wsf uses a WMI Query Language (WQL) data query to retrieve the desired information. Thus, to view all instances of the Exchange_FolderTree class (i.e., to view all the public folder hierarchies) on an Exchange server, you use the WQL data query
Select * From Exchange_FolderTree
Web Figure 1 (http://www.winnetmag.com/microsoftexchangeoutlook, InstantDoc ID 41022) shows sample data from running GetCollectionOfInstances.wsf against this query. You can narrow the query's scope by specifying a public folder hierarchy's name, an administrative group, or both. Therefore, you can use such queries as
Select * From Exchange_FolderTree Where Name='Public Folders'
Select * From Exchange_FolderTree Where AdministrativeGroup= 'First Administrative Group'
Select * From Exchange_FolderTree Where Name='Public Folders' And AdministrativeGroup= 'First Administrative Group'
The name property should contain the name of the public folder hierarchy you want to query. In these examples, I set this property to Public Folders, the name of the default public folder hierarchy in Exchange. If you have another public folder hierarchy in your Exchange organization, make sure you change this name accordingly. The same applies for the AdministrativeGroup property.
Updating Administrative Notes
The script AdministrativeNote.wsf updates the AdministrativeNote property of an Exchange_PublicFolder instance. Listing 1 shows an excerpt from this script. AdministrativeNote.wsf uses the same structure as the scripts in Part 1. After AdministrativeNote.wsf initializes the constants, the script makes the WMI connection and locates the target public folder by submitting a WQL query, as callout A in Listing 1 shows. The script assigns the returned WMI collection to the objWMIInstances variable.
If the target public folder is a root folder in the hierarchy, you set the cPublicFolderPath constant to a string such as /My Public Folder/. Note that you must enclose the path between two forward slashes (/) because that's the way WMI represents paths. If the target public folder is a child folder that's deeper in the hierarchy, the constant's value needs to reflect that location. For example, if you want to access a folder called My Second Child Folder that's deeper in the hierarchy, you would set the cPublicFolderPath constant to a string such as /My Public Folder/My First Child Folder/My Second Child Folder/. This setup makes the script easy to use and avoids confusion when locating a public folder in a tree if some public folders have the same name but different paths.
You could use the Url property, which is unique to each public folder, to identify the target public folder. However, using the Url property is more difficult than specifying the path because this property uses a numeric identifier that's hard to find. To find the path, all you need to do is open the Microsoft Management Console (MMC) Exchange System Manager (ESM) snap-in and look at the Public Folder Instances container in the Information Store (IS) that's hosting the target public folder.
Next, the script enumerates the objWMIInstances collection, which contains the public folder you want to update. If the given path exists, the target public folder is typically the only item in the collection because the path is unique for each public folder in a given hierarchy. If you have identical paths across different hierarchies, you need to narrow the query's scope by using the Exchange_PublicFolder class's FolderTree property. Although AdministrativeNote.wsf doesn't take this situation into consideration, the WQL data query would look something like the following:
Select * From Exchange_PublicFolder Where Path="/My Public Folder/" And FolderTree= 'Exchange_FolderTree.Name= "Public Folders", AdministrativeGroup= "First Administrative Group"'
Next, the script assigns the cAdministrativeNote constant value to AdministrativeNote property, as callout B in Listing 1 shows. The code at callout C in Listing 1 invokes the SWbemObject object's Put_ method to save the update in WMI.
For AdministrativeNote.wsf to successfully locate the specified public folder on an Exchange server, all the ISs must be mounted on the server to which the script connects. Otherwise, you'll encounter CDOEXM error code 0xC1030AF3.
You can adapt AdministrativeNote.wsf so that it updates other read/write properties of the Exchange_PublicFolder class. However, three read/write properties—ReplicationMessagePriority, StorageLimitStyle, and ReplicationStyle—require specific values that have particular meanings. Web Table 1 and Web Table 2 (http://www.winnetmag.com/microsoftexchangeoutlook, InstantDoc ID 41022) provide the values for the ReplicationMessagePriority and StorageLimitStyle properties, respectively. Table 1 contains the values for the ReplicationStyle property. Let's take a closer look at the ReplicationStyle property and its sister property, ReplicationSchedule.
Updating Replication Schedules
ReplicationStyle and ReplicationSchedule, which govern public folder replication, can be two of the more challenging properties to update. If you set ReplicationStyle property to any value in Table 1 except Custom, you don't need to set the ReplicationSchedule property because the ReplicationStyle property's value automatically determines the value of the ReplicationSchedule property. If you set the ReplicationStyle property to Custom, you must also set the ReplicationSchedule property.
The script Replication.wsf demonstrates how to use the ReplicationStyle and ReplicationSchedule properties to set a custom replication schedule. ReplicationSchedule is an array in which each item is an instance of the Exchange_ScheduleInterval class. This WMI class provides information about the start and stop times in the public folder replication schedule.
Replication.wsf stores the schedule information in the cReplicationSchedule constant as a comma-delimited string. Each substring contains three components:
- a day of the week, which is followed by a colon
- the replication start time, which is followed by a hyphen
- the replication stop time
The string that the cReplicationSchedule constant is currently set to is Sun:0000-0100,Mon:0100-0200,Tue:0200-0300,Wed:0300-0400,Thu:0400-0500,Fri:0500-0600,Sat:0600-0700. However, you can easily change the replication schedule by customizing this string.
Although this string contains the replication schedule, you can't simply assign that string to the ReplicationSchedule property because the schedule information needs to be in a particular format. So, the script first uses the ConvertStringInArray function to convert the string into an intermediate array called arrayReplicationSchedule. Using a comma as a delimiter, this function parses the string into seven substrings (Sun:0000-0100, Mon:0100-0200, and so on), which the script assigns to arrayReplicationSchedule.
After the script makes the WMI connection to the Exchange 2003 server, the script uses a For Each...Next statement to transform the array of substrings into an array of Exchange_ScheduleInterval instances. Listing 2 shows that part of the encoding process.
As the code at callout A in Listing 2 shows, the script uses the ConvertStringInArray function to parse twice each substring in arrayReplicationSchedule.The first parsing uses a colon as a delimiter to isolate the day from the time. The second parsing uses a hyphen as a delimiter to isolate the start time from the stop time.
With the three components (i.e., day, start time, and stop time) isolated, the script converts the schedule information into the format that the Exchange_ScheduleInterval class's StartTime and StopTime properties use. The format is a date and time representation that the Distributed Management Task Force (DMTF) defines. Depending on the DMTF format, the script structures the replication start and stop times as
where DD is the day (00=Sunday, 01=Monday, and so on), HH represents the hours (in 24-hour format), and MM represents the minutes (in 15-minute increments). The asterisks specify that you want a relative point rather than an absolute point in the calendar. The replication schedule must be in Universal Time Coordinate (UTC) format, which means that the schedule times visible in the ESM console shift in relation to the Greenwich Mean Time (GMT) time zone in which your Exchange 2003 server resides. For the sake of simplicity, Replication.wsf doesn't perform a validation test to verify whether the DMTF-formatted start and stop times have the correct format.
As the code at callout B in Listing 2 shows, a Select Case statement constructs the DMTF-formatted start and stop times, based on the day of the week. The script assigns the start and stop times to the strStartTime and strStopTime variables, respectively. Next, the script creates a new instance of the Exchange_ScheduleInterval class and assigns the strStartTime and strStopTime variables' values to the class's StartTime and StopTime properties, respectively. The script then stores this schedule information in a new array called arrayReplicationScheduleInstances. After arrayReplicationScheduleInstances contains the complete replication schedule, the script exits the For Each...Next statement.
Next, the script uses a WQL query to find the public folder that the cPublicFolderPath constant specifies. After locating that public folder, the script sets that folder's ReplicationSchedule property to arrayReplicationScheduleInstances. The script then sets the ReplicationStyle property to 0 (i.e., Custom).
Creating and Deleting Public Folders
Before you try to create or delete a public folder, you must meet several key conditions:
- If you want to create a public folder, the public folder hierarchy must already exist. If the public folder hierarchy exists but not on the Exchange server on which you want to create the public folder, you must make sure that the hierarchy is replicated on that server.
- The public folder hierarchy must be associated with an IS.
- The associated IS must be mounted.
To create or delete a public folder, you need to create or remove the Exchange_PublicFolder class instance representing that public folder. However, the Exchange_PublicFolder class doesn't expose any methods that directly create or delete public folders, so you need to use indirect approaches, which the scripts CreatePublicFolder.wsf and DeletePublicFolder.wsf demonstrate.
CreatePublicFolder.wsf. To create a public folder, you use the SWbemServices object's Get method to retrieve the Exchange_PublicFolder class definitions, then use the SWbemObject object's SpawnInstance_ method to create a new instance of that class, as the code in Listing 3 shows. You then use the Exchange_PublicFolder class's Name and the ParentFriendlyUrl properties to assign the public folder's name and location in the hierarchy, respectively. The ParentFriendlyUrl property's value must be an HTTP pointer to the parent public folder of the folder you're creating. This value can't contain any blank spaces; if an HTTP pointer contains a space, you must replace that space with the characters %20. If you're unsure of the HTTP pointer, you can find it by running GetCollectionOfInstances.wsf against the WQL query
Select * From Exchange_PublicFolder
DeletePublicFolder.wsf. To delete a public folder, you must first locate that folder by submitting a WQL query, as the code in Listing 4 shows. After you locate the Exchange_PublicFolder instance to delete, you invoke the SWbemObject object's Delete_ method, as the code at callout A in Listing 4 shows.
Performing Other Operations
The Exchange_PublicFolder class's methods—AddReplica, RemoveReplica, SendChanges, Copy, Move, Rename, PropagateSettings, and Synchronize—let you perform other public folder operations. Each method requires specific input parameters.
AddReplica and RemoveReplica. The AddReplica and RemoveReplica methods let you create and remove replicas, respectively. The only parameter for these methods is the distinguished name (DN) of the IS in which you'll manage the replicas. The Exchange_FolderTree class's AssociatedPublicStores property holds the DN of the relevant IS for the specified public folder hierarchy. Thus, to find the DN, you can run GetCollectionOfInstances.wsf against the WQL query that exposes the Exchange_FolderTree class instances. After you know the DN, you can use a script such as CreateReplica.wsf. This script, which you can download from the Exchange & Outlook Administrator Web site, uses the AddReplica method to create a replica.
SendChanges. The SendChanges method sends a public folder's modifications to its replica. The method requires two parameters: an integer that represents how often (in terms of number of days) to send the modifications and the DN of the public folder's IS.
Synchronize. The Synchronize method forces synchronization between public folders and their replicas. The Synchronize method doesn't take any parameters.
Although Synchronize and SendChanges both perform synchronization, they differ in two ways. Both Synchronize and SendChanges send the local changes to the replicas, but the Synchronize method also sends changes of other replicas to the local folder. Moreover, the Synchronize method occurs against all replicas, whereas the SendChanges method lets you select the replicas with which you want to synchronize.
Copy and Move. With the Copy and Move methods, you can copy and move public folders. These methods require one parameter: the friendly URL of the folder you want to copy or move. It's the same type of URL as the ParentFriendlyUrl property you specify when creating a public folder. The script CopyPublicFolder, which you can download from the Exchange & Outlook Administrator Web site, demonstrates how to use the Copy method to duplicate a public folder.
Rename. The Rename method lets you rename a public folder. This method requires one parameter: the public folder's new name.
PropagateSettings. The PropagateSettings method disseminates a public folder's settings to all its child folders. This method takes one required and one optional parameter. The required parameter is an integer that represents the flags (i.e., settings) for the public folder. Each flag corresponds to a bit in a bit pattern. The integer is the sum of the values representing the desired bits. Web Table 3 shows the bits and their values. The optional parameter is a Boolean value that specifies whether to stop the execution of the method if an error occurs.
Take Small Steps
Programmatically managing Exchange's public folders has always been a challenge, mainly because of Exchange's lack of management tools. Exchange 2003's new WMI providers and classes make public folder management through scripts much easier. A script exploiting all the capabilities of the Exchange_PublicFolder and Exchange_FolderTree classes would be quite daunting. But, as you've witnessed in this article, if you look at each capability separately, the classes are easier to understand. I'll take this same approach in Part 3 of this series, in which I'll show you how to programmatically manage queues with a new set of WMI classes dedicated to Exchange queue management.