Recently I did an install for a product from Avaya called OutlookReserver. It's a neat little Outlook AddIn that allows conference calls on an enterprise bridgeline to be scheduled just like any other Outlook meeting request. Unfortunatly the install the vendor provided was far from desirable. Administrator privledges were required to install the application and an interactive utility needed to be ran for each users profile to establish a form in their calendar. After doing some research I found out that this really must be done through the client and could not be done through a back side exchange server process. My design came together and I realized to make this an Hard Core Setup I had to solve two problems. First was to find a way to automate the interactive utility, second was a way to impersonate interactive user while running my install as SYSTEM through SMS2003. First I'll discuss automation of the form publish.
Outlook supports automation through MAPI. With all the versions of Office out there we want to use late binding. Basically we just observe what the interactive utility is accomplishing and reverse engineer it. We also find out that by only doing what we need to do we can eliminate the annoying security alert popups from Outlook. A simplistic prototype looks something like this:
Set NameSpace = Outlook.GetNamespace("MAPI")
Set Folder = NameSpace.GetDefaultFolder( 9 )
Set Item = Outlook.CreateItemFromTemplate("confcall.oft")
Set Form = Item.FormDescription
Form.Name = "Conference Call"
Form.PublishForm 3 , Folder
So we put this in a VB6 project, compile the EXE and slap it into the install. We also give it some logic to know if it's ever ran before and put it in the Run Key for AllUsers.
Now on to the second problem: We push silently as system. This is the case even if the interactive user goes to Control Panel Advertised Programs and manually runs the advertisement. I can't just simply put the EXE in a Custom Action, it would run as SYSTEM. So what we do is compile an ActiveX EXE in VB6. It's simply a wrapper for the Run command that gets exposed as a DCOM server. Why DCOM instead of COM? Because by making it a DCOM server I can configure it to run as the Interactive User instead of the Launching User. I build it as a merge module ( so that I can reuse it in future installs ) and add it to the redistributables of my project. Then I just place a VBScript custom action in my project that looks something like this:
set oCoMsiHelper = CreateObject("coMsiHelper.Shell")
oCoMsiHelper.RunAsLoggedOnUser "publish.exe", Session.Property("INSTALLDIR"), 1
set oCoMsiHelper = nothing
Bingo! The merge module installs and configures my DCOM server to run as the Interactive User then my custom action comes by at the end and publishes the form silently for the user. Hard Core Setup Engineering has occurred. The user is spared from having to do any manual steps. From his perspective, it just works.