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 Outlook=CreateObject("Outlook.Application")
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
Item.Close 1
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.
Hi Chris,
ReplyDeleteI am struggling on this part from quite a long time. Will it be possible for u to share your merge module with me or tell me the logic to change the dcom settings from system to interactive user. I also use SMS 2.0 to deploy packages across network.
Thanks and I must tell that your posts on community are very informative.
Thanks,
Uttam Mathur
Uttam,
ReplyDeleteThe key is the AppID table. You use com extraction to extract the COM Data in the EXE but then you have to create an entry in the AppID table to make it a dcom server. Then look at the last column, RunAsInteractiveUser - set it to 1. This causes the HKCR\AppID\GUID\RunAs registry value to be set to Interactive User.
Now in your custom action when you create the object it will be running with the privledges of the logged on user.
Hallo Chris
ReplyDeleteI am facing a problem with the installshield MSI package installation.
In the msi package, there are some custom actions, run via InstallScript. I have included the redistributable Merge Module provided by Installshield itself, Scripting Engine 9.0.
Everything works fine, and the package is getting created without any hassle.
It was getting installed online on machines with users having admin priviledges by some external tool .
This tool is having admin priviledges and installs it on the target machine. Everything works fine till now.
NOw, there is a need to install the MSI package on the machines, again online via net, where in the users are non admins, and have restrictive access. The installations fails as the tool runs the main msi fines, but the inbuilt Scripting engine is somehow prevented from actioning, and the whole installation fails.
Can you help me out on this? Any sort of pointers would be highly appreciated.
Thanks
Hi Guru-
ReplyDeleteYour using a version of InstallShield that is several years old and had a problem with DCOM AppID settings in that deployment scenario. If you can, upgrade to InstallSHield 12 which has a redesigned scripting runtime that will solve your problem. Otherwise checkout this article for some insite on how to changing the DCOM from Interactive User to Launching User so that the CA's will work when pushed as Admin with a Non-Admin user logged on.
http://www.software-repackaging.com/index.php?q=Deploy+Apps+ISScript
This is the only site I see referencing an object in your CreateObject("coMsiHelper.Shell") statement. It errors out about that object when I try to run it ebedded in an MSI. Is the name a typo or does something else install that object?
ReplyDeleteThis solution is quite old and I'm not sure I'd do it this way anymore. The class you mention is something I had written that allowed an installer initiated as System to create processes as the Interactive User. Today I'd probably run the installer as the interactive user and leverage windows installer elevation properly.
ReplyDelete