Sunday, April 17, 2005

Installing an Internet Explorer ActiveX Control

This post is different from my usual posts, mainly because I have no idea what I am talking about! Well, at least I am admitting it this time!

I am tasked with creating an installation for an intranet type application. I need to create a shortcut to a URL and install a client side ActiveX control. For the sake of argument lets make it a fairly common one, such as the Crystal ActiveX viewer control. Sounds pretty simple, eh?

Let's go over a typical usage scenario. Hopefully, when designing applications and their deployment packaging you have some made-up profiles of typical users. Lets make up a few for our purposes. "Bob the system admin," "Mary the power user," and "Joe the restricted user" should be good enough. We can be a bit more specific and cover XP SP2 users, users with severely restricted ActiveX Browser settings, and non-IE browser users as well, but lets ignore these for now.

Essentially, Joe has a problem. We can give him the URL to the web application or even create a shortcut and/or favorite for him. The problem is, the first time he tries to run a Crystal Report, he gets a security warning, and the Crystal ActiveX control does not install. Of course, it is because he has no permissions to install software, even if everything else we ignored above is in good shape. Incidentally, if we can't figure out that Joe's problem is that he is a limited user, you can try the CDLLogViewer application to find out why.

Bob and Mary never have issues with the system. In fact, if Bob and/or Mary perform the same steps as Joe everything works, and Joe logs in later on, even Joe can view and print reports. The problem is that Bob and Mary would never run reports on the system. Heck, Bob doesn't even launch the application. Bob may even deploy the install package using SMS or Group Policy.

In the corporate network world, pretty much everyone is a Joe. There are a few Privileged Mary's, and even less Bob's. To make all this work, Bob needs to install applications for the likes of Joe. This behavior is not only acceptable, but practically expected.

So how would Steve, our installation guru, make all this work? He would not only need it to work, but be practically bulletproof.

Option 1: The easiest approach. 99% of the time, this is synonymous with the wrong approach. We can extract the Crystal Reports ActiveX viewer cab file, read the .inf file to figure out what it is doing, add the files to a MSI project selecting the proper registration options, create the shortcut file, and be done with the project in under 20 minutes.

Why it doesn't work: Since Joe is not the only user of the machine (remember Mary and Bob?), any updates to the control will cause the MSI-based installation to screw up at some point. If the control is updated by Mary, and Bob uninstalls the application, the component/reference count then causes havoc with Mary by possibly removing the file on uninstall. Effectively, we have precluded the normal installation/updating/removal of the ActiveX Viewer by repackaging it in an MSI. More information on the hazards of this approach can be found on MSDN in the "Registry Details" page. Bad stuff.

Option 2: Install the shortcuts as in Option 1. Call the appropriate API's to install the CAB file from the web server. In this case, (after a bit of digging through MSDN I see this process is called "Internet Component Download" or ICD for short) we need to call CoGetClassObjectFromURL.

Why it doesn't work: Referring to the ICD link above, we assume the web server is up and running at installation time - #1 in the "Download and install process". We also assume that WinVerifyTrust returns a value that is compatible with the setting for ActiveX controls for the Zone in which the server we are pulling the cab file from resides - #2 in the "Download and install process". Last, but not least, we are assuming that good old Bob didn't muck with the CODEBASE setting of the Internet Search Path.

Option 3: Completely decimate the user's machine by querying the IE Security Settings, saving them, adding the server to a trusted zone, modifying the zone parameters to set the ActiveX settings appropriately, call CoGetClassObjectFromURL, after it succeeds, set everything back to the way it was.

This seems like a heck of a lot of work, but it appears to be the only way to bulletproof an installation of an ActiveX component. Plus, we ignored several issues. If the default browser was (or will be) Firefox or even Lynx, a shortcut to this URL will always fail to display the reports. To solve this problem, an EXE wrapper would need to be written to host the IE control to assure that IE is actually the browser engine used to access the page. Joel, the API war is far from over - it just made things more complicated!

Of course, I'll get to play around with these API's and see if installing the cab file from a file:// UNC path changes anything. I'll report back what I find. If anyone else has already "solved" this problem using an approach I haven't considered, please let me know. In all likelihood, I'll end up calling CoGetClassObjectFromURL, and if it fails, try to provide some meaningful feedback to the user as to why the installation can not succeed and let Bob worry about the corner cases. After all, he ultimately created them.

UPDATE: Please see Part II of this post!

8 comments:

Troy Phillips said...

Actually I think that the most viable way forward is a variation of option 1 that you haven't considered. Most enterprise organisations in this situation will actually take a "snapshot" of the changes made during the installation of the OCX to generate an MSI. This will include the changes in the ModuleUsage subkey.

Your option 3 is a demonstration of the perils in ignoring the KISS directive, and the reasons why many enterprise customers choose to repackage installations from ISVs.

Anonymous said...

I don't understand why you just can't register the COM component per-user. With Windows 5.0 and later the HKCU\Software\Classes key stores per-user activations (see
http://bonemanblog.blogspot.com/2004/09/debugging-dll-registration-issues.html)

Steven Bone said...

>I don't understand why you just can't register the COM component per-user.

Well, the goal here is to have the admin install the product, then have any other user be able to use the control. A per user activation scheme will not work. Additionally, registering an activex control via the IE cabinet file download/install will write to the LM keys - and we want to emulate this behavior. We could install the activex control as part of a per user installation elevated if the policy settings are correct. That solution, although it would 'work' does not meet the other goal of being updatable via the web page for admin users if need be.

Anonymous said...

Well that is not what the blog entry said that you were trying to accomplish. It said that you wanted Joe to be able to install and run an application which used the Crystal ActiveX.

I did some testing here and for Windows 2000 SP4 and Windows XP SP2 a normal user account doesn't even see a prompt from IE 6 to install a .CAB file; I suppose that is because the browser "knows" the user cannot write to HCR. The solution then seems simple; instead of using a .CAB file create an .EXE file with something like IExpress. Reference that in the OBJECT tag but also add an anchor tag with the .EXE so that "Joe" can "Open/Run" the ActiveX installation. And, of course, change the registration code of the ActiveX to use HKEY_CURRENT_USER\Software\Classes\CLSID instead of HCR\CLSID. Then he or any other user can both install and update the control.

Steven Bone said...

>It said that you wanted Joe to be able to install and run an application...

Actually, we wanted Joe (and everyone else) to be able to run the application that uses the control after someone more privledged installed it on the same machine. Asssuming MSI, we can allow Joe to install it elevated, but other installation technologies would not allow Joe to install it - unless the installation was written for a Current User installation only, which would break the other requirement of install once and have any other user on the machine be able to run the application.

>normal user account doesn't even see a prompt from IE 6 to install a .CAB file...

You are correct - my post was wrong in this regard - IE will not even prompt a restricted user to install an ActiveX control.

>create an .EXE file with something like IExpress

This is another possible solution. It actually won't work in all situations, though. Since Joe can't write to certain locations on the disk, we need to install the AX to a nonstandard path. If another user updated the control, Joe's would not be updated. You would need to put some version checking in the AX control so it can tell Joe he needs to rerun the installation exe. Finally, it would require repackaging and testing the AX logic both for OBJECT tag and the EXE method. This is really not a method that can be used as a pattern for other ActiveX installations.

It does raise an issue that my solution has from post #2 - Joe will not know if he is using an out of date version of the control.

Anonymous said...

Excuse me for saying this but your requirements seem to keep changing. This makes it difficult to suggest an appropriate solution.

Here's what I now understand to be the behavior that you desire:
1) A user who is a member of the Administrators group should use an MSI to install the Crystal ActiveX control. (Why I am still not sure)
2) A user who is a member of the Administrators group should be able to visit a Web page that updates the control to the latest version.
3) Other users on the machine should be able to use the control.

You should be able to do this by repackaging the ActiveX with an MSI file and by creating a .CAB installation for the Web page that will update the control.

If you instead do what I suggested in the previous post your life will be simpler. You will only need to create the .EXE for the Web page. When a new version of the control is available just update the .EXE and the OBJECT tag version numbers so that Power Users or Administrators will automatically install the new control. Normal users would not be automatically prompted to install the updated version; but then again - they were never automatically prompted to install the first version. If it really bothers you then include a check in the Web page for the current version of the control and display that alongside the anchor tag link that a normal user would use for manual installation/updating of the control. Even this may not be necessary if you just ensure that the .EXE installs ActiveX into the directory that IE would put it in - the "Downloaded Program Files" folder to which all users can write. If a Power User or Administrator happened to update the control before Joe logs in the next time then he would be using the current version.

Vadim Rapp said...

Regarding the objections to #1:

If the users are not supposed to install activex control from the internet, then of course they are not supposed to update it as well, for the same reasons. Every new version of the control has to be reviewed by IT department, tested if it does not introduce new problems with existing known company applications, and only then deployed - of course in the same repackaged way as the previous version, and as an update to it. All of which makes sense if new version brings in some new benefits: for example, if it only closes some security hole that is closed by the proxy server anyways, then probably it's not important.
Most, if not all, activex controls have setting that turns off their self-updating efforts; such setting has to be found and included in the MSI.
This is how we do it in our network with Adobe Reader and with Flash.

The MSI can be deployed per-machine by group policy or by SMS, i.e. it's deployed in elevated process. It also can be deployed per-user by group policy, if it's really important to make it available only for selected users on the same machine.

As for other considerations, such as Bob uninstalling what Mary has installed - in properly authored MSI this is all taken care of automatically.

Unknown said...

Hi,One way to accomplish your goal is to create a review web page. This type of web page can be built with many different type of Web Design Cochin programs.Thanks.....