Today I was debugging a problem with a script I was writing when I stumbled upon an interesting problem. The script takes data from my clipboard, processes it, formats an HTML report then creates an Outlook email message which it inserts the formatted report and sends it out to a list of recipients.

The script did everything that it should but ran into a problem when it called into the Outlook object model using COM. The standard way to instantiate a COM object is to first attempt to connect with Outlook if it is already running, otherwise run Outlook specifically for the sake of the script:

use Win32::OLE;
my $Class = "Outlook.Application";
my $Outlook = Win32::OLE->GetActiveObject( $Class ) || new Win32::OLE( $Class );
die if ! defined( $Outlook );

This is exactly where my script was failing. The calls into Win32::OLE would pause for several seconds but always return undef. How odd. Calling into Win32::OLE->LastError() to determine the error yielded an equally confusing error message:

0x80080005: "Server execution failed"

Of course there was no easy way to learn why the COM server execution had failed. Needless to say, after tinkering around a bit I discovered that if I first quit Outlook the script executed perfectly. It was only if I was running Outlook that the script failed. How odd.

To make a long (and frustrating) story short, the problem was that I was running the script from a CMD.EXE window which was elevated (“Run as Administrator”). When I would run Outlook from a non elevated process (as a normal user would) there appeared to be a process elevation mismatch.

From this I suspected that COM instantiation would fail if the COM server and COM clients run with mismatched Integrity Access Levels. A quick trip over to MSDN ( validated my suspicion:

COM security is aware of integrity levels and does not allow lower-integrity clients to bind to class instances running at a higher integrity level.

In my case the perl script was running at a higher integrity level than Outlook. So it would appear that this integrity level issue would notapply.  The workaround that I have decided to employ is to run the script in a non-elevated CMD.EXE shell. This should work fine until I can find a more suitable solution; assuming one exists.