Migrating Applications to Microsoft Outlook 2000

Jim Groves
Microsoft Corporation

October 1999

Applies To: Microsoft® Outlook® 2000

Summary: This article details the issues a developer might encounter when running an Outlook 98- or Outlook 97-based application on Outlook 2000. (9 printed pages)

Introduction

You’re finally done putting the finishing touches on your Microsoft® Outlook® 98–based collaboration application. The Microsoft Exchange Server public folders are in place, with their painstakingly customized forms complete with Visual Basic®, Scripting Edition (VBScript) code that makes everything work great. People in your organization have begun flocking to your public folders, where they are able to share information with each other in ways that would have been impossible just a few months ago, had it not been for your hard work and the collaboration features of Outlook and Exchange Server. You’ve even received a few pieces of fan mail in your Outlook Inbox.

But you can’t sit back and admire your handiwork for long, because your boss has just informed you that the order has come down from the top IT management: The entire company is moving to Microsoft Office 2000—including Outlook 2000—as soon as practicable. That means that in a month or so, everyone using your collaboration application will be using Outlook 2000, not Outlook 98, to access it.

Naturally, you can’t help but wonder how the new version of Outlook will “break” your carefully constructed application. Will Outlook 2000 be able to handle the custom forms? Has anything in the Outlook object model changed that will affect the VBScript code in the forms? What other nasty surprises might be in store for you?

Fortunately, chances are excellent that when your users upgrade to Outlook 2000, they won’t notice any appreciable difference in how your application works. Although many features were added to Outlook 2000 to make it an even better platform for developing collaboration applications, considerable effort was expended to ensure that applications designed for earlier versions of Outlook would work unchanged.

For example, the tools used for customizing forms, as well as the underlying form technology itself, have not changed between Outlook 98 and Outlook 2000. With rare exceptions (which are noted in this article), a form created by using Outlook 97 or Outlook 98 should work unchanged with Outlook 2000. In fact, it’s unlikely that your application’s users will notice any difference among the versions.

In addition, although the Outlook object model has been significantly extended for Outlook 2000, existing objects and class members have not been significantly changed, so that any VBScript or Visual Basic for Applications (VBA) code that accesses the Outlook 98 or Outlook 97 object model should run without modification (again, exceptions are noted in this article).

Finally, no file formats have changed in Outlook 2000. That means if your application relies on personal folders (.pst) or form template (.oft) files, you do not have to recreate those files for use with Outlook 2000.

Is Everything Guaranteed to Work Unchanged?

If all this sounds too good to be true, it is … sort of. As I suggested earlier, there are a few, quite rare, exceptions.

One exception that should be obvious is the case where code relies on the design of the Outlook user interface, such as code that accesses the command bar of the Outlook explorer or inspector. As you would expect, any code that assumes that a command exists on a particular menu or toolbar will break if that command is moved in a subsequent version of the user interface.

In addition to such apparent compatibility problems, there are other, more obscure, “gotchas” that might affect an Outlook 97- or Outlook 98–based application that is moved to Outlook 2000. In brief, these are:

The remainder of this article describes these issues in detail and suggests how you can work around them if they affect your application.

Distribution List Items in Contacts Folders

A new type of item supported by Outlook 2000 is the distribution list, which consists of a list of e-mail addresses that you can refer to by using a single name when you send a message. Unlike the personal distribution list provided by the Outlook Personal Address Book, the Outlook distribution list item can contain contacts as well as other types of e-mail addresses and is available when Outlook is configured to run in Internet Mail Only mode as well as in Corporate or Workgroup mode.

The fact that Outlook distribution lists are stored in the same folders as contacts can cause problems. Because it would be very unusual for an Outlook 98 contacts folder to contain anything other than contact items, existing applications could contain code that assumes that every item in a contacts folder is a contact.

The following code sample shows how an application might make this mistaken assumption.

Function CountHomeless() As Integer
‘ Counts the number of contacts in the user’s Contacts folder that
‘ don’t have addresses and displays the number in a message box.

    Dim objOlApp As New Outlook.Application
    Dim objOlNS As Outlook.NameSpace
    Dim objFolder As Outlook.MAPIFolder
    Dim colContacts As Outlook.Items
    Dim objContact As Outlook.ContactItem
    Dim intCounter As Integer

    ‘ Get the collection of contacts in the default Contacts folder.
    Set objOlNS = objOlApp.GetNamespace(“MAPI”)
    Set objFolder = objOlNS.GetDefaultFolder(olFolderContacts)
    Set colContacts = objFolder.Items

    ‘ Step through collection to find contacts with no addresses.
    For Each objContact In colContacts
        If objContact.HomeAddress = ““ And _
                objContact.BusinessAddress = ““ Then
            intCounter = intCounter + 1
        End If
    Next

    CountHomeless = intCounter
    MsgBox “The number of contacts without addresses is “ _
        & CountHomeless & “.”

    Set objOlApp = Nothing
    Set objOlNS = Nothing
    Set objFolder = Nothing
    Set colContacts = Nothing
    Set objContact = Nothing
End Function

There are actually two problems with this example. The first, and probably more obvious one, lies in these statements:

Dim objContact As Outlook.ContactItem
...
For Each objContact In colContacts

Clearly, if colContacts contains any items other than contact items, a “type mismatch” run-time error will occur.

You could prevent that error from occurring by declaring objContact as a generic Object variable, but that wouldn’t solve the less-obvious problem that would result in a run-time error. This problem appears in this statement:

If objContact.HomeAddress = ““ And objContact.BusinessAddress = ““ Then

Only contact items support the HomeAddress and BusinessAddress properties, so a run-time error will occur if objContact refers to any object other than a ContactItem.

Fortunately, a few lines of code can solve this problem. That is, you can continue to strongly type the object variable and use type-specific properties simply by replacing Set colContacts = objFolder.Items with the following:

Set colContacts = objFolder.Items
strFilter = _
    “[MessageClass] > ‘IPM.Contacs’ AND [MessageClass] < ‘IPM.Contacu’“
Set colContacts = colContacts.Restrict(strFilter)

The Restrict method of the Items collection object acts as a filter, removing all items from the collection that don’t match the parameter statement. In this case, Restrict removes all items that are not ContactItem objects, that is, items whose MessageClass property is not set to IPM.Contact or a derivative custom message class (such as IPM.Contact.MyContact; using the conjunction of “greater than” and “less than” expressions ensures that the filter matches any string that begins with “IPM.Contact”). That ensures that when the code iterates through the collection, it will encounter only contact items.

Another article on this site, “Working with Members of an Items Collection,” deals in greater detail with the challenges of handling unexpected items in a collection.

Contact Linking and “Down-Level” Clients

Outlook 2000 introduced contact linking, the ability to link almost any item with one or more contacts. For example, you can link the contact item of a client you are meeting to the corresponding appointment item on your calendar, making it easy to look up information about the client.

In Outlook 97 and Outlook 98, task and journal items have fields in which you can enter the names of people associated with the task or journal item. In the case of a task item, the field is strictly a text box; names added to the list are not resolved to valid addresses. There is no way to programmatically add items to this list in Outlook 97, although the ContactNames property was added to the TaskItem object in Outlook 98 to let you manipulate this list.

The form for the journal item does allow you to select names from your address book, so the Contact field can contain a link to an item in your Contacts folder. In either Outlook 97 or 98 you can access this list either through the item’s Recipients collection or through its ContactNames property.

For Outlook 2000, a Links collection was added to each Outlook item, making it possible to link the item to one or more contact items. The default task and journal forms were redesigned to display the contents of the Links collection as the item’s associated contacts. In addition, the forms were designed to “import” the linked contacts of task and journal items created by Outlook 97 and Outlook 98, copying them into the new Contacts field that represents the Links collection. For Outlook 2000 users who do not access shared task or journal folders, the process is nearly seamless.

The difficulty arises, however, if there is a mix of Outlook 97, Outlook 98, and Outlook 2000 users who try to access shared task or journal folders. That is because Outlook provides varying levels of “backward compatibility” for task and journal contact linking. The following chart shows how Outlook 2000 interacts with Outlook 97 and Outlook 98 when working with the same item.

Item Action Result
Task Outlook 2000 user opens an existing item with linked contacts for the first time. Contact items are added to Links collection and new Contacts field.
Task Outlook 97/98 user changes Contacts field in an item previously opened by an Outlook 2000 user (that is, the Links collection is not empty). Outlook 2000 Links collection and new Contacts field are not updated and so are out of sync with the Contacts collection and Outlook 97/98 Contacts field.
Task Outlook 2000 user changes Contacts/Links list. Results replace contents of item’s Contacts collection and hence the Outlook 97/98 Contacts field.
Journal Outlook 2000 user opens an existing item with linked contacts for the first time. Contact items are added to Links collection and new Contacts field.
Journal Outlook 97/98 user changes Contacts field in an item previously opened by an Outlook 2000 user (that is, the Links collection is not empty). Outlook 2000 Links collection is not updated and so is out of sync with the Outlook 97/98 Recipients collection.
Journal Outlook 2000 user changes Contacts/Links list. Results are not copied to item’s Recipients collection or to Outlook 97/98 Contacts field, which are now out of sync with the Outlook 2000 Contacts field and Links collection.

Although it would be possible to write code that could deal with changes by Outlook 98 and Outlook 2000 users (due to difficulties in accessing the contents of the Contacts collection of a task item, it would be nearly impossible to deal with changes made by Outlook 97 task users), doing so would be a daunting endeavor, requiring you to match the free text entries of the Outlook 98 contacts fields to the names of contacts in a shared folder. For example, an Outlook 98 user could simply enter “Chris” as a contact, assuming that everyone knew who Chris was, when in fact there might be contact items for several people named Chris in the contacts folder. Worse yet, the code would have to try to account for nicknames (is Chris short for Christopher or Christina?). Your code would be forced either to remove an unmatched item, or to require the Outlook 2000 user (who was not the one who entered the unmatched name and so might not know who was intended) to choose the correct match.

Clearly, if your application relies on contact linking for tasks or journal items, it will work best if everyone who uses the application is running Outlook 2000 because of its superior and pervasive contact-linking abilities.

ShowFormPage, HideFormPage, and One-Off Forms

Outlook forms are usually published in a forms library so that they can be available to the users who need them. Forms can be published in an organizational forms library maintained by Microsoft Exchange Server, in a folder-specific forms library, or even in a user’s personal forms library.

When a user creates an item of a particular type, Outlook opens the corresponding form so the user can enter information before saving the item in a folder or sending it to another user. If the form is changed in the process (because the user enters design mode and changes the form, or VBScript in the form changes the form itself), Outlook saves or sends the changed form definition with the item, creating what is called a “one-off” form. Although this is useful for ensuring that whoever opens the item will have the modified form available, it also means that if the form contains VBScript code, Outlook will display a macro security warning when the item is opened. (Outlook doesn’t display the warning for forms that are published in the organizational forms library because they are assumed to come from trusted sources.)

Note   For more about the macro security warning, see “How to Prevent the VBA Macro Security Warning in Outlook 2000.”

In Outlook 97 or Outlook 98, if the VBScript code in a form calls the HideFormPage or ShowFormPage method to hide or show a page on the form, the form is considered to have been changed, so its definition is saved or sent with the item. As a result, even if the form is otherwise identical to the version published in the forms library, any user who opens the item will see the macro warning.

This is widely regarded as undesirable because it makes it difficult to “gracefully” change how a form works depending, for example, on who is using it. That is, an application designer might want to present different form pages to a user, depending on the user’s relationship to the item (author, editor, or reviewer, for example). Doing this at run time will always result in the macro warning being displayed, even if no real change has been made to the form or (more pertinently) to the form’s VBScript code after it has been published in the organizational forms library.

Because this is a problem for so many application developers, Outlook 2000 no longer creates a one-off form if the only change to the form is the result of calls to the HideFormPage or ShowFormPage method.

Of course, often a solution to one problem will lead to new problems, and this turns out to be no exception. Some application designers noticed how Outlook 97 and Outlook 98 create one-off versions of a form in these situations, and so designed their applications to depend on this behavior. These applications will no longer work with Outlook 2000.

Take a workflow application as an example. The application could use a form with multiple pages, one for each person who is to receive the item to process and then pass it on to the next person in the chain. In Outlook 97 or Outlook 98, the first person in a chain can click a button that will hide the page intended for the first person, reveal the page for the second person, and then forward the item to the second person. When the second person receives the form, it will show only the page meant for him or her. In other words, the application relies on the form becoming a one-off form in order to persistently store the form’s state between the time it is sent and when it is received, even though the form itself didn’t really change.

If the first user is running Outlook 2000, however, the item received by the second user will use the version of the form published in the organizational forms library, not the one-off version that would have been produced by Outlook 97 or Outlook 98.

Fortunately, although the issue is complex, the solution is relatively simple: All that is required is that something else be done to force the form to be sent as a one-off form. One possibility is to specify when publishing the form that the form definition should always be sent with the item (set on the Properties tab of the form when it is in design mode).

Another way of ensuring that an item will be sent with a one-off form is to make a real change to the form at run time, even if it is a trivial change. For example, at design time you could add a label to the form and set its Visible property to False. At run time, when you want to force the form definition to be sent with the item, just use VBScript code to change the Caption property of the label. This will be enough of a change that any version of Outlook will send the modified form definition with the item.

Optional CDO and EFD Support

In an effort to reduce the “footprint” that Outlook requires on the user’s system, Setup does not automatically install support for the Electronic Forms Designer (EFD) or Collaboration Data Objects (CDO) when installing Outlook 2000. Most Outlook users don’t need this support, so for them this is the right approach. However, if your application relies on EFD or CDO, you must ensure that the required software is installed on your user’s computers.

Support for Collaboration Data Objects

Formerly known as OLE Messaging and Active Messaging, CDO is an object model that gives applications more direct access to the Messaging Application Programming Interface (MAPI) used by Outlook to structure its data storage than does the Outlook object model. Programming with CDO is more flexible than MAPI because, unlike MAPI, CDO does not require C or C++ as the programming language. Instead, CDO can be accessed through Visual Basic and Active Server Pages (ASP), as well as Visual C++® and any other development tool that creates Component Object Model (COM) objects.

As noted, CDO support is not automatically installed with Outlook 2000 the way it is in Outlook 98. If you have developed an application that relies on CDO to access Microsoft Exchange Server data, users running Outlook 2000 will not be able to use the application unless they have installed CDO support.

If you are planning to roll out Outlook 2000 to your organization and have applications that use CDO, you can use the Custom Installation Wizard provided as part of the Office Resource Kit to create a customized setup that installs the CDO support software along with Outlook 2000.

If users in your organization have already installed Outlook 2000, it is easy for each of them to install the CDO support.

To install CDO support

  1. Click Start, point to Settings, and then click Control Panel.

  2. Double-click the Add/Remove Programs icon.

  3. In the list, click Microsoft Office 2000 or Microsoft Outlook 2000, and then click Add/Remove.

  4. Click Add or Remove Features.

  5. Click the plus sign (+) next to Microsoft Outlook for Windows to open it.

  6. Click Collaboration Data Objects, and then click Run from My Computer.

Support for Electronic Forms Designer

When Outlook 97 was released, it was designed to be a replacement for the Microsoft Exchange Server client application. This means, among other things, that it must support forms designed by using the Electronic Forms Designer (EFD), sometimes also called the Exchange Forms Designer, the tool used to create custom forms for the Exchange Server client.

This support is provided by default in Outlook 97 and Outlook 98. However, by the time Outlook 2000 was released, Outlook had become the standard Exchange Server client for Windows®-based computers, and increasing numbers of customers were designing custom forms by using Outlook forms instead of EFD forms. Consequently, the decision was made for Outlook 2000 not to install support for EFD forms by default.

The result is that Outlook 2000 users cannot view items created with EFD forms unless the Electronics Form Designer Runtime software is installed on the computer.

Again, if you are planning to roll out Outlook 2000 and want to provide support for EFD forms, you can use the Custom Installation Wizard to create a customized setup to install the Electronic Forms Designer Runtime when Outlook 2000 is installed.

If users in your organization have already installed Outlook 2000, they can also use Control Panel to install the Electronic Forms Designer Runtime.

To install the Electronic Forms Designer Runtime

  1. Click Start, point to Settings, and then click Control Panel.

  2. Double-click the Add/Remove Programs icon.

  3. In the list, click Microsoft Office 2000 or Microsoft Outlook 2000, and then click Add/Remove.

  4. Click Add or Remove Features.

  5. Click the plus sign (+) next to Microsoft Outlook for Windows to open it.

  6. Click Electronic Forms Designer Runtime, and then click Run from My Computer.

Conclusion

As you can see, there are few changes in Outlook 2000 that could adversely affect users of previous Outlook versions, and those changes are likely to involve a relatively small percentage of users.

The changes described in this article are the predictable results of intentional changes made to Outlook. There might be some unexpected consequences of other changes that could create problems for users upgrading to Outlook 2000, however. If you have not yet deployed Outlook 2000 in your organization, it is strongly recommended that you search the Microsoft Knowledge Base (www.microsoft.com/support/kb.htm) for up-to-date information that might have an effect on your deployment plans.