Become a Columnist Microsoft Exchange Site Microsoft Support SiteMSDN Exchange Site

   

Subscribe to OutlookExchange
Anderson Patricio
Ann Mc Donough
Bob Spurzem
Brian Veal
Catherine Creary
Cherry Beado
Colin Janssen
Collins Timothy Mutesaria
Drew Nicholson
Fred Volking
Glen Scales
Goran Husman
Guy Thomas
Henrik Walther
Jason Sherry
Jayme Bowers
John Young
Joyce Tang
Justin Braun
Konstantin Zheludev
Kristina Waters
Kuang Zhang
Mahmoud Magdy
Martin Tuip
Michael Dong
Michele Deo
Mitch Tulloch
Nicolas Blank
Pavel Nagaev
Ragnar Harper
Ricardo Silva
Richard Wakeman
Russ Iuliano
Santhosh Hanumanthappa
Steve Bryant
Steve Craig
Todd Walker
Tracey J. Rosenblath
 
 

Tips and Tricks for Exchange Development using CDO with VB and VBS event sink with Exchange 2000

The following article is a list of my experiences as somewhat of a part-timer in Exchange Development and lists the issues, problems and workarounds that I have found and used.

This Document was updated on 7/5/2002 click here to see what's new

Know where to look

One of the most important things when tackling a development project is to know where to look when you strike a problem (for me this is not a question of if its when!). The first port of call for any Microsoft problem is to start with a TechNet search, this will show you any errors, problems, workarounds or hotfixs for the component you are trying to develop. I recommend you look here before you start any coding as this can save you several hours down the track troubleshooting known problems. If TechNet has failed you and all those books you brought all contain the same piece of sample code that doesn't solve your problem then here's some good sites to try.

msdn.microsoft.com  The Microsoft RTFM site (in time understanding will fix most problems) (Some of us has less time then others though)
www.cdolive.com  This is the best site around for CDO programming has some great sample code as well www.devx.com  This is another great site for general programming issues and has some very good free articles on developing with Exchange 2000.
http://www.wsd2d.com/wsD2D/  Another good site that offers advice on developing the Web storage system and provides sample code

Newsgroups are another invaluable source of information when trying to solve problems, you often find someone has already experienced the same problem as you and may already have a solution. The best newsgroups I have found are the Microsoft Public groups which can be accessed via the web at http://groups.google.com/groups . This web interface provides a searchable index of all the newsgroup posts, once you have worked out a good searching method you'll be amazed at the depth of information that can be uncovered. And if you really get stuck you can post your problem in the newsgroup, don't expect a direct answer though but you should get pointed in the right direction.

My Experiences - Using the ICreateRegistration Interface to keep your VB event sink secure

In a previous article I explained the problems of security when using event sinks. You can provide registration security in VB event sinks using the ICreateRegistration Interface's register() function. If implemented this function is called on registration of an event sink. Notes from the field : I have experienced problems with this function when trying to work out which user was trying to register an event , with a synchronous event sink you can use the IExStoreEventInfo interface to work out who fired an event by retrieving either their usersid or userguid. Trying to do this with the register function returned nothing when I called the usersid method and returned  the exchange mailbox guid when I called the userguid method. As a workaround for this problem I implemented security based on what mailbox this event was being registered on. This makes the code less flexible but I found it isn't too much of a hassle to recompile the code for each mailbox . The other method I use is to implement notification code in the register function by placing some simple CDO code to send a mail to the administrator whenever somebody registers this event. (I found this a better method because it allows you to identify any users who are trying to circumvent the system). here's an example of using both methods

Function ICreateRegistration_Register(ByVal pEventInfo _
As Exoledb.IExStoreEventInfo, ByVal bstrURLItem As _
String, ByVal lFlags As Long) As Long
On Error Resume Next
Dim Msg As CDO.Message
Set Msg = New CDO.Message
With Msg
    .To = "administrator@AD1"
    .Subject = bstrURLItem
    .TextBody = testbody
    .From = "newb2@AD1"
    .Send
End With
If InStr(bstrURLItem, "file://./backofficestorage/AD1/MBX/newb2/") <> 1 Then
    ICreateRegistration_Register = -1
Else
    ICreateRegistration_Register = 0
End If
End Function

Modify existing WSS objects (Email ETC) with VBS scripts

By default when you open objects within the Web Storage System programmatically you have read-only access to those objects. If you wish to write back to these objects you need to state when opening the object that its for write access. The ESDK states you should use one of the following constants such as adModeReadWrite in your open statement to gain write access to an object. If your using VBS script these constants don't work, in this case you need to use the numerical equivalent. For adModeRead this is 1 and for adModeReadWrite this is 3. To get access to all the header fields inside a mail object you can use the fields collection. When using the fields collection you need to use the update method to perform an update before saving the results back to the object. The following is an example of opening an e-mail with write permissions and marking the mail as read

set msgobj1 = CreateObject("CDO.Message")
msgobj1.DataSource.Open WSS-URL, ,3
msgobj1.Fields("urn:schemas:httpmail:read").value = true
msgobj1.fields.update
msgobj1.datasource.save

Porting your VBS Code to VB

To implement event sink code into a busy production environment you should consider for security and performance reasons compiling your code as VB DLL's (or C++). If like me you've developed your code using VBS you now need to look at porting it to VB. To start this process you need to create a new activeX DLL project. Within your new class the first thing you need is for your class to implement interfaces for the events its going to handle by declaring these in the general section of the class. For example if your writing an Async event sink you would place the following in the general section of your class

Implements IExStoreAsyncEvents

After this you then need to include code for all the methods defined in the IExStoreAsyncEvents interface. To get the correct syntax for these use the object browser in VB (press F2). An Example for the Async event is

Private Sub _
IExStoreAsyncEvents_OnSave(ByVal pEventInfo As Exoledb.IExStoreEventInfo, ByVal bstrURLItem As String, ByVal lFlags As Long)
End Sub

Private Sub _ IExStoreAsyncEvents_OnDelete(ByVal pEventInfo As Exoledb.IExStoreEventInfo, _
ByVal bstrURLItem As String, ByVal lFlags As Long)
End Sub

You need to create a project reference to the EXOLEDB Type library and any other type libraries that you want to use eg Microsoft CDO for Exchange 2000  type Library. Once you have done this you are ready to go the easiest and most direct method is to cut and paste your VBS code straight into the VB interface. I've found on most occasions this will work just fine, for performance and efficiency sake you should clean the code up with proper variable declarations and error checking. You should also review your code to see if you can take advantage of the extended features of VB to increase performance.

Using the Pevent info and Iflags the other event sink parameters

When an event sink is fired there are three parameters that are passed from the Web storage system to the event sink. The most notable and usable is the bstrURLItem which contains the URL of the item that caused the event to fire. But there are two other parameters that are also passed which can be just as useful if you know how to use them.

The first of these is PeventInfo which is "a pointer to an IExStoreEventInfo Interface" this can be used to get more information on the object that caused the event to fire. A useful thing you can do with this is using the geteventitem method you can retrieve certain columns from the ADO record of the object that fired the event. This can be particularly useful in a onsyncdelete event where you can access the email that is being deleted (which caused the event to fire) normally this would be locked by the delete process. This allows you to retrieve information from the email such as the body content and subject etc. An example of this is show below.

Set DispEvtInfo = pEventInfo
Set ADODBRec = DispEvtInfo.EventRecord
wrile.writeline ("Subject : " &  ADODBRec.Fields("urn:schemas:mailheader:subject").Value)
wfile.writeline ("Textbody of message : " & ADODBRec.Fields("urn:schemas:httpmail:textdescription").Value)

The second of these parameters is IFlags this contains information about what sort of action caused this event to fire. For example if its a new mail being delivered or was it because an email was deleted etc. To use this in a coding context you need to do a bitwise And to determine the  iflags status for example to determine if a event was fired for a newly delivered email you would do

Const EVT_NEW_ITEM = 1
Const EVT_IS_DELIVERED = 8
If (lFlags And EVT_IS_DELIVERED) Or (lFlags And EVT_NEW_ITEM) Then

end if

Conclusion

Its my intention to keep growing this document as I encounter more problems over the course of my adventures in the Web Storage System. So till then Share and Enjoy :)


Disclaimer: Your use of the information contained in these pages is at your sole risk. All information on these pages is provided "as is", without any warranty, whether express or implied, of its accuracy, completeness, fitness for a particular purpose, title or non-infringement, and none of the third-party products or information mentioned in the work are authored, recommended, supported or guaranteed by Stephen Bryant or Pro Exchange. OutlookExchange.Com, Stephen Bryant and Pro Exchange shall not be liable for any damages you may sustain by using this information, whether direct, indirect, special, incidental or consequential, even if it has been advised of the possibility of such damages.

Copyright Stephen Bryant 2008