The CDO library is powerful and approachable, but you can run into problems if you aren't careful when writing your code. This section introduces some tips and tricks you should use, and some pitfalls you should avoid. Many of the pitfalls I outline are from personal experience—they are quite frustrating, so I recommend you read this section before attempting to write any CDO code.
Let's jump right in! Look at the following code and try to figure out what is wrong:
MsgBox oSession.Inbox.Messages.GetFirst.Subject For Counter = 2 To oSession.Inbox.Messages.Count MsgBox oSession.Inbox.Messages.GetNext.Subject Next |
The same subject will appear in your message box as many times as the number of messages in your Inbox. Despite what the code looks like, it won't recurse through your Inbox, because if you don't explicitly assign an object to a variable, CDO will create needed temporary objects for each statement and then discard the object after the statement. This means that you will instantiate a new object every time you loop in the For…Next loop. Each new object does not maintain the old state of the previous temporary object, so the object will always point to the first message in the collection. So you should set explicit variables to refer to a collection to get the desired functionality. The following listing shows the rewritten code, which behaves as expected:
Set oMessages = oSession.Inbox.Messages Set oMessage = oMessages.GetFirst MsgBox oMessage.Subject For Counter = 2 To oMessages.Count Set oMessage = oMessages.GetNext MsgBox oMessage.Subject Next |
Whenever possible, avoid the use of temporary objects, as demonstrated in the previous pitfall. Don't spend a lot of time scouring your code to get rid of temporary objects unless you are a major offender of this rule. Sometimes you'll want to use temporary objects to represent the different CDO objects rather than declare variables. However, using temporary objects should be an exception and not a rule in your coding practices.
To improve the performance of your Visual Basic CDO applications, always try to use early binding by declaring your CDO variables as specific CDO objects. Not only will you find that writing your code is easier because Visual Basic can perform type-checking as well as help you finish statements in your code, but you'll also find that your users will thank you for the application's improved performance.
You use the dot operator to set a property, call a method, or access another object. Essentially, each dot represents additional code that must be executed. If you can reduce the number of dot operators in your code, you can improve performance of your application. One way to do this is to use With statements. For example, consider the following code snippet, which has no With statements and is inefficient both from a performance perspective and an ease-of-reading perspective:
MsgBox "Text: " & oSession.Inbox.Messages.GetFirst.Text MsgBox "Subj: " & oSession.Inbox.Messages.GetFirst.Subject |
Now consider the next bit of code, which does use the With statement. This code will execute faster:
With oSession.Inbox.Messages.GetFirst MsgBox "Text: " & .Text MsgBox "Subj: " & .Subject End With |
The rule of thumb is to think of dots in your code as expensive.
When writing CDO applications using ASP, the best tip I can give you is to use the code from this book to handle your logons and logoffs from CDO and ASP sessions. The most common pitfall that new and even experienced CDO developers run into when writing ASP applications is forgetting to insert the correct impersonation code into the Global.asa, which properly destroys the CDO and ASP sessions. When a user attempts to access your Web application after IIS attempts to use the wrong context to destroy these objects, the application returns the ASP 0115 error, which means that a trappable error has occurred in an external object.
The final pitfall that I can help you avoid in your ASP applications is the CDOE_FailOneProvider error, which occurs when you try to access the root folder of the Public Folder InfoStore object or a folder in the mailbox of a specific user. Many developers have run into this error, especially those who are new to ASP programming. The common cause of this error is not changing the security context that IIS is using to access the Exchange server by authenticating the Web user using either Windows NT Challenge/Response authentication or Windows NT Basic authentication. Therefore, the Web user is trying to access the root of the Public Folder store or a user's mailbox using the Windows NT credentials of the anonymous IIS user account. Frequently this anonymous account doesn't have security permissions to access the Exchange server. When this is the case, CDO returns CDOE_FailOneProvider to indicate an error in accessing the information.
The easiest way to solve this problem is to use the logon and logoff code from the examples in this book. These examples, especially the Helpdesk application, authenticate users by prompting them for their Windows NT credentials before attempting to access any Exchange Server information.
As you have seen throughout the chapter, many of the objects in the CDO library support the Fields property. The Fields property returns a Fields collection, which allows you to find custom and built-in properties using identifiers supplied by either Exchange Server or MAPI. One of the most powerful yet elusive features is this set of Exchange Server and MAPI properties. These properties allow you to perform operations on Exchange Server and Outlook items in situations where CDO does not provide objects. For example, in the Helpdesk application, user information is pulled out of the AddressEntry property by using the unique identifiers for department name, office location, and other properties. If you did not know these properties existed, you would think that their information was inaccessible from CDO because CDO does not provide explicit objects for them.
Another scenario illustrating why these unique properties are valuable is that of setting up folders to work offline. The documentation on this process is hard to find, but MAPI provides a property called PR_OFFLINE_FLAGS (&H663D0003), which contains a zero (0) if the folder is not currently set to synchronize offline and a 1 if it is. By using this property, you can programmatically set any folder in the mailbox of a user to synchronize offline—the user does not have to set synchronization manually through Outlook. If this field does not exist in the Fields collection already, you will need to add it to the collection by using the Add method.
The best place to find the information about the properties you can use with the Fields collection is in the CDO help file under "MAPI Property Tags," or in the Platform Software Development Kit (SDK) section of the MSDN Library under "Database and Messaging Services," "Messaging API (MAPI)," "Reference," and then "MAPI Properties." For Exchange Server properties, look in the MSDN Library and perform a keyword find on the Index tab for "Microsoft Exchange Server Message Properties." All of these properties combined can provide new functionality to your applications, even though CDO may not provide explicit objects for this functionality.