Jump to content


This is a ready-only archive of the InstallSite Forum. You cannot post any new content here. / Dies ist ein Archiv des InstallSite Forums. Hier können keine neuen Beiträge veröffentlicht werden.
Photo

Component installed to two different locs


5 replies to this topic

RayKode

RayKode
  • Full Members
  • 58 posts

Posted 26 August 2010 - 19:50

Hello everyone.

Very simply .........

App1 installs a com .dll into a folder. (Let's say it is the root of drive C.)
The component has:
Com Extract at Build set to yes.
Share to No.
And the .dll is set as key.

App2 installs the same .dll into a “different” folder. (Let's say it is in Program Files.)
I use the exact same component guid for this .dll in App2 as I did in App1.

After App2 is installed and I look in the registry I see that the COM paths for this .dll are all pointing to the Program Files folder.
As it SHOULD. (This is a good thing.)

Now, comes the rub.
If I uninstall App1.
The .dll in the root of drive C (which was installed by App1) goes away. (A good thing.)
The .dll in Program files (which was installed by App2) remains on the pc. (Another good thing.)
“BUT”, the registry entries associated with the .dll, all disappear from the registry. (NOT such a good thing.)


“If however” ……… .

I rebuild App1 to NOT use COM Extract at build for the .dll but instead chose to "self register" it.

I install App1.
I install App2.
I uninstall App1.
The registry entries for the .dll remain in the registry, (A very GOOD thing indeed.)
And how I thought, things would work if I shared the component GUIDs.)

It's too late to change App1.
The application (and this .dll) are already are on thousands and thousands of pcs.)

The developers of App2 want to be have both App1 and App2 exist on the same pc at the same time until such time as the user deems that App2 works as advertised.
At which time, App1 can be uninstalled.

App2 is using any entirely separate folder structure than App1 uses.


Anyone have an idea of how I might install this .dll (in App2) so that when App1 is uninstalled, the registry entries for the .dll remain ?

Thanks in advance for any advice or suggestions.


Glytzhkof

Glytzhkof
  • Moderators
  • 1,447 posts

Posted 26 August 2010 - 23:06

COM wasn't really originally designed for anything but per-machine single file installation - meaning that the server should be installed in a single location common to all applications and users and registered there. In the distant past that used to be System32.

In recent years it has become more common to install a local copy of a COM file in several application folders, though I seriously question the wisdom of this due to the potential to miss security fixes with scattered COM files all over the place, and the associated registration problems that result from multiple installed files.

For this multi-file installation to work all GUIDs (CLSID, Interface, AppId, etc..) for the COM file must be changed as well as the ProgId. If you don't several files will share a single registry location for its registration and this is the cause of your problem. Both installations treat the registry keys as "their own" and thereby removing them on uninstall. In other words: each Windows Installer component built with COM extract will see the file and all associated registry items as an atomic installation unit and install and uninstall it as a whole.

There are some ways around this:
  • First of all you can change the COM registry information for App2 as described above. Generally lots of work and even more testing, but if the dll files are actually different in content and behavior, this is the only sane approach. This will mean that the dll files will NOT share the same code base and you should branch the code in source control since you may need to deliver updates to both development lines.
  • Second you can try to use what is called registration-less COM. This means that you extract the registry information file and put it in a manifest XML file next to the COM file for app2. On newer versions of windows the manifest will be loaded and there will be no need for registry keys. If you do this the file must NOT be marked COM extract, and there must be no registry keys added by the component that installs the dll. The XML file should be possible to create via a Wizard in Installshield.
  • Finally it's worth noting that if you launch the application via an advertised shortcut this should trigger a self repair and add back the registry keys for app2 after the uninstall of app1. This is very unclean, but should work. Self repair will ONLY be triggered via an advertised shortcut, not if you run a regular shortcut or launch the exe directly from explorer.

The reason it works with self-registration is probably because this enforces old-style dll reference counting via the SharedDLL ref-count in the registry. You don't want to trust this.

Edited by Glytzhkof, 26 August 2010 - 23:08.

Regards
-Stein Åsmul

RayKode

RayKode
  • Full Members
  • 58 posts

Posted 27 August 2010 - 13:11

Thank you for taking the time to consider my issue.
And for your response. (Which, by the way, I think is excellent.)

As it turns out, originally, my problem .dll, WAS implemented as Reg Free COM by App2.

In fact, the PRIMARY purpose of App2 is to implement a Reg Free COM version of App1.

Then for some reason, one of the App2 developers decided that the functionality associated with this particular .dll, was not working correctly.

So a decision was made to have me change App2 to install and register this .dll, in a second location on the hard drive.

Except for the registry uninstall business, things DO work. (For App1 and App2.)

I didn’t even think about the "repair" option.
Never even occurred to me.
I will now.

What I DID do however, (don't laugh at this) is ........

I wrote a custom action (that runs on install of App2) that adds an entry to the SharedDlls registry key for the App1 version of my problem .dll.
Setting the value to "2".

When App1 is uninstalled, the value drops to "1".
The fact that that the App1 version of the .dll remains on the pc (Because the SharedDlls value is still set to a “1”), become more of an embarrassment at this point, than a cause of any real functionality issue.

But, the registry entries for my problem.dll, continue to point to the second location of the .dll. (A GOOD thing.)

I also wrote a second CA (that runs on un-install of App2)that removes the remaining SharedDlls entry and the folder which holds the .dll installed by App1.

It works.
But it's ugly.
Very ugly.


Thanks once again for your time and efforts on my behalf.

I DO appreciate both.

Ray in Wisconsin





MSIYER

MSIYER
  • Full Members
  • 90 posts

Posted 31 August 2010 - 08:10

Whenever we have such a case, its probably because we overlooked rules laid down by the Windows Installer. We have to follow the rules to avoid any such problems.

Whenever two or more applications developed by the same vendor use a common component, the component should be installed at a common place, for example:
App1 and App2 both use abc.dll
App1 installs at {ProgramFiles}\{CompanyName}\App1
App1 installs at {ProgramFiles}\{CompanyName}\App2
App1 and App2 should both install the abc.dll at the same location, say at {ProgramFiles}\{CompanyName}\CommonFiles

For this we also need to set the msidbComponentAttributesSharedDllRefCount bit so that the dll is treated as shared. This will help installer to perform version checks(if versioned components are used) prior to installing any dll.

Also it is the developer's responsibility to have version number resource with the dll. Changing the name of the dll(in code) for App2 dll should also help(my opinion). Whenever we have a change in the dll we should increment the version number.

In all other cases whichever dll is installed last would overwrite all COM info the registry with its own. Installer cannot perform any version check.

Cannot you try to install App2 dll into the same folder as App1? Are there any problems(in terms of requirements) in doing so?



Glytzhkof

Glytzhkof
  • Moderators
  • 1,447 posts

Posted 31 August 2010 - 21:33

As MSIYER says setting the msidbComponentAttributesSharedDllRefCount is required when you install in a common place, but it has nothing to do with Windows Installer reference counting. It actually means the legacy-style SharedDLL reference counter in the registry is incremented AS WELL as having the component registered by Windows Installer. This ensures that non-MSI installers can reference count the file in their fashion. The legacy reference counting can be found at HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\SharedDLLs.

Changing the dll file name won't cure the registry clash unless you also change all GUIDs used by the dll.
Regards
-Stein Åsmul

MSIYER

MSIYER
  • Full Members
  • 90 posts

Posted 02 September 2010 - 06:16

Thanks Glytzhkof for your inputs.

RayKode should still look for installing both the components in the same location (making sure the dlls are versioned)as I mentioned in the earlier post.

As RayKode uses the same component GUIDs, the installer reference count mechanism will recognize that two different Apps are using the same component.
And the uninstallation problem will not occur.

The new reference mechanism is essentially the same as SharedDll concept in the following aspect:
Instead of searching for HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\SharedDLLs installer maintains a reference count based on component GUIDs.
Thus, if we have the same component GUIDs for the component in two apps but the installation path for the component differs in the apps, no proper reference count will be maintained. That is, if App1 installs the component to Path1 and then App2 installs the same component with the same component GUID to Path2, reference mechanism is broken.

The only thing to make sure is that the dll is versioned and the newer version is backward compatible.

Creating two different components with different GUIDs in App1 and App2 will also be of no use.

Else, as Glytzhkof mentioned we have to change COM interface GUIDs and the name of the dll. This should then be treated as a diferent component.

Edited by MSIYER, 02 September 2010 - 12:26.