As every single one of you know, when leveraging Outlook (or doing any sort of COM Interop) through .NET, the objects we interact with are RCW objects that point to the actual Outlook COM interface.

For whatever reason, you may find that it is required to check if two objects represent the same Outlook object. For example, in the following snippet (which is purely demonstrative code, of course it would be ridiculous to have something like the following in a real world application):

Explorer firstExplorer = Application.ActiveExplorer();
Explorer secondExplorer = Application.ActiveExplorer();

As you can see, we are setting both Explorer objects equal to the active explorer. Since both calls are happening right after each other, chances are that those two objects are representing the same Outlook Explorer instance.

Behind the scenes, the first call to ActiveExplorer() creates a new RCW pointing to the Explorer COM interface. The second call to ActiveExplorer() will actually increment the RCW internal reference count by 1.

If we want to check if these two objects are equal, we would do something like:

firstExplorer == secondExplorer

or

firstExplorer.Equals(secondExplorer)

Both are going to give the same result: true. The reason for the result is of course due to the fact that only a single RCW is created per process per object. Because of this, both objects are being set to the same RCW object, making them identical.

Other than the tidbit regarding the RCW, this should all be very obvious to you.

Now, let’s say, for purposes of aggressive resource maintenance and cleanup, you are applying some of the strategies pointed out in my previous article to these two Explorer objects. Let’s say you want to isolate both managed Explorer objects from all others created (the reasons as to why you may want to do this, are in my previous article and will not be covered here). You would do something like so (the following code would typically occur in different places; again, this is demonstrative code):

Explorer firstExplorer = Application.ActiveExplorer();
IntPtr pUnkFirstExplorer = Marshal.GetIUnknownForObject(firstExplorer);

Explorer secondExplorer = Marshal.GetUniqueObjectForIUnknown(pUnkFirstExplorer);

Alright. The code above will create unique RCW objects pointing to the active Explorer COM interface. So, what will happen if we compare the two again, like so:

firstExplorer == secondExplorer

You will find that the result in this case is false. Obviously, this is because the two objects are now set to different RCW instances. Despite this, the fact remains that they are actually pointing to the same Outlook Explorer.

So, if you are in a situation where you have multiple Explorer objects like above, and you need to determine if they represent the same Explorer, how would you go about doing that?

The solution here is very simple. If two RCW objects are pointing to the same instance in COM-land, then the IUnknown interface retrieved from both objects will end up being equivalent.

IntPtr pUnkFirstExplorer = Marshal.GetIUnknownForObject(firstExplorer);
IntPtr pUnkSecondExplorer = Marshal.GetIUnknownForObject(secondExplorer);

bool result = pUnkFirstExplorer.Equals(pUnkSecondExplorer);

Marshal.Release(pUnkFirstExplorer);
Marshal.Release(pUnkSecondExplorer);

The above code will result in true.

If the managed Explorer objects were actually representing different Explorers (let’s say one was set to an Explorer opened to the mail folder, the other object set to an Explorer opened to the calendar folder), then the above code would correctly return false.

Matt Weber

I'm the the Senior Software Architect at Emergingsoft where I lead the software development team. I am also the owner of this website. I enjoy well-designed code, independent thought, and the application of rationality in general. You can reach me at matt@badecho.com.

 Leave a Reply

(required)

(required)

You may use these HTML tags and attributes: <a href="" title="" rel=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

 
   
© 2012-2013 Matt Weber. All Rights Reserved. Terms of Use.