This website uses cookies. By clicking Accept, you consent to the use of cookies. Click Here to learn more about how we use cookies.
Turn on suggestions
Auto-suggest helps you quickly narrow down your search results by suggesting possible matches as you type.
- Revenera Community
- :
- InstallShield
- :
- InstallShield Forum
- :
- Re: Bug in "Shared" Component handling during major upgrades
Subscribe
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Subscribe
- Mute
- Printer Friendly Page
- Mark as New
- Subscribe
- Mute
- Permalink
- Report Inappropriate Content
‎Jul 06, 2007
10:34 AM
Bug in "Shared" Component handling during major upgrades
Hi all,
I create a new topic for this as I believe I may found a bug in the "Shared" handling of InstallShield 2008.
Let me explain how to reproduce the problem.
1. First create a project with 2 component, containing an exe or dll file. One component has the "Shared" option enabled, the other not.
2. Now create a 1.0 Version of the project and install it on a test machine (i recommend VMWare).
3. Now create a 2.0 Version of your project, assume that you reorganized the components and assign new GUIDs to them. Enable the Shared Option on both components. For major upgrades select Install first, the removed unused files.
4. Now perform an upgrade installation on your testmachine and monitor the following registry key:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\SharedDLLs
5. You will see that InstallShield sets the Count to 2 on the exe/dll files of BOTH components.
6. At the end the old setup is being removed, and now the following happens! The component that had the Shared Option enabled in the OLD setup gets decremented to the count 1. But the other component which didn't have the Shared Option enabled is not being decremented, it remains at 2.
The following error of this is, that the component is NOT uninstalled during uninstallation, as the Installer still thinks it is needed somewhere. I know this is a rather rare condition, but I believe it is a bug within InstallShield.
I create a new topic for this as I believe I may found a bug in the "Shared" handling of InstallShield 2008.
Let me explain how to reproduce the problem.
1. First create a project with 2 component, containing an exe or dll file. One component has the "Shared" option enabled, the other not.
2. Now create a 1.0 Version of the project and install it on a test machine (i recommend VMWare).
3. Now create a 2.0 Version of your project, assume that you reorganized the components and assign new GUIDs to them. Enable the Shared Option on both components. For major upgrades select Install first, the removed unused files.
4. Now perform an upgrade installation on your testmachine and monitor the following registry key:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\SharedDLLs
5. You will see that InstallShield sets the Count to 2 on the exe/dll files of BOTH components.
6. At the end the old setup is being removed, and now the following happens! The component that had the Shared Option enabled in the OLD setup gets decremented to the count 1. But the other component which didn't have the Shared Option enabled is not being decremented, it remains at 2.
The following error of this is, that the component is NOT uninstalled during uninstallation, as the Installer still thinks it is needed somewhere. I know this is a rather rare condition, but I believe it is a bug within InstallShield.
(5) Replies
- Mark as New
- Subscribe
- Mute
- Permalink
- Report Inappropriate Content
‎Jul 06, 2007
12:48 PM
This is Windows Installer behavior. By changing component GUIDs yet delivering the same file to the same place, one is breaking component rules, opening the door for this undesirable result.
- Mark as New
- Subscribe
- Mute
- Permalink
- Report Inappropriate Content
‎Jul 09, 2007
03:40 AM
Hrm so what I am supposed to do? Not changing the components guids? I have no other choice!
The reason is I want to change the setup to install a win32 and x64 Version of the core component based on the System Version.
This works well, I could manage to enable the right component on the right system using conditions.
But one of the components of course has to have a new GUID.
The reason is I want to change the setup to install a win32 and x64 Version of the core component based on the System Version.
This works well, I could manage to enable the right component on the right system using conditions.
But one of the components of course has to have a new GUID.
- Mark as New
- Subscribe
- Mute
- Permalink
- Report Inappropriate Content
‎Jul 09, 2007
06:24 AM
I found threads with simular problems in InstallShield 12 from other peoples:
http://community.macrovision.com/showthread.php?t=170424&highlight=shared+registry
http://community.macrovision.com/showthread.php?t=170598&highlight=SharedDLLs+registry
So if nothing else comes I have to find a workaround, again.
http://community.macrovision.com/showthread.php?t=170424&highlight=shared+registry
http://community.macrovision.com/showthread.php?t=170598&highlight=SharedDLLs+registry
So if nothing else comes I have to find a workaround, again.
Not applicable
- Mark as New
- Subscribe
- Mute
- Permalink
- Report Inappropriate Content
‎Jul 09, 2007
09:06 AM
A single component (identified by its component code) is defined by a single resource installing to a single location. Any new versions of the component should also not break previous versions of the component. By changing the component code of a file installing to the same location, you've violated those rules and created a state where this can happen.
If a single file is installing to a single location then the component code should and must remain the same.
Further, in your testing using something like process monitor, you'd see that the responsible process is msiexec.exe and not setup.exe (installshield). Thus, this is likely behavior from Windows Installer based on component rules being violated.
This leads me to believe that you've selected the option to "Install Setup then Remove Unneeded files", which doesn't allow you to violate component rules at-will as we warn in the little bit of help text in the Upgrades view.
If a single file is installing to a single location then the component code should and must remain the same.
Further, in your testing using something like process monitor, you'd see that the responsible process is msiexec.exe and not setup.exe (installshield). Thus, this is likely behavior from Windows Installer based on component rules being violated.
At the end the old setup is being removed, and now the following happens! The component that had the Shared Option enabled in the OLD setup gets decremented to the count 1. But the other component which didn't have the Shared Option enabled is not being decremented, it remains at 2.
This leads me to believe that you've selected the option to "Install Setup then Remove Unneeded files", which doesn't allow you to violate component rules at-will as we warn in the little bit of help text in the Upgrades view.
- Mark as New
- Subscribe
- Mute
- Permalink
- Report Inappropriate Content
‎Jul 09, 2007
09:42 AM
I need to use the option "Install Setup then Remove Unneeded files" as otherwise the whole registry gets removed during the remove of the old setup - which kills all my old application settings. Wether or not I am breaking any rules, I need this to be working, I can't tell all the customers to manually backup there settings before installing the new major version, this is just crap.
So I created a workaround myself which works pretty well in my environment with all kind of tests. For all others who run into the same problem, here is a dirty workaround.
1. Create a new new Installscript like this:
In short RealResetReferenceCount can be used on any component in any feature with any file extension you need to. In my sample I only use it on one.
ExFn_ResetReferenceCount will be the function that can called in a custom action.
2. Create a new Custom Installscript Action, function name will be "ExFn_ResetReferenceCount". Only use it in Install Exec Sequence, I selected "After RemoveExistingProducts" to make sure it will be executed at the very last.
What the script does, it loops trough all files within the given component, checks if there is a value in the ShareDLLs key. If there is a value, it will reset the count back to 1. Works perfectly in my case, as only one version of the application can be installed.
So I created a workaround myself which works pretty well in my environment with all kind of tests. For all others who run into the same problem, here is a dirty workaround.
1. Create a new new Installscript like this:
#include "ifx.h"
export prototype ExFn_ResetReferenceCount(HWND);
export prototype RealResetReferenceCount(STRING, STRING, STRING, STRING);
// REALFUNCTION
function RealResetReferenceCount(szFeature, szComponent, szFileType, szInstallDir)
STRING sQuery, sFile, szFilePath, sRegKey, sCount;
NUMBER nListPos, nCount, nSize, nvType, nReturn;
LIST IncrementList;
begin
IncrementList = ListCreate(STRINGLIST);
sRegKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\SharedDLLs";
sCount = "0";
// Get list of files within a component ....
sQuery = szComponent ^ szFileType;
if(FeatureFileEnum(MEDIA, szFeature, sQuery, IncrementList, NO_SUBDIR) == 0) then
// Set new Count number default
nCount = 1;
nvType = REGDB_NUMBER;
RegDBSetDefaultRoot(HKEY_LOCAL_MACHINE);
// Iterate through the list, and increment reference count ..
nListPos = ListGetFirstString(IncrementList, sFile);
while(nListPos != END_OF_LIST)
// Create registry value name
szFilePath = szInstallDir + sFile; // already contains backslash "\\"
// Only write if available
nReturn = RegDBGetKeyValueEx(sRegKey, szFilePath, nvType, sCount, nSize);
if(nReturn == 0) then
// Write new value into registry
NumToStr(sCount, nCount);
RegDBSetKeyValueEx(sRegKey, szFilePath, nvType, sCount, -1);
endif;
// Next file
nListPos = ListGetNextString(IncrementList, sFile);
endwhile;
endif;
end;
function ExFn_ResetReferenceCount(hMSI)
// To Do: Declare local variables.
begin
// Call da real function
RealResetReferenceCount("Feature1\\Subfeature1", "Component1", "*.exe", INSTALLDIR);
end;
In short RealResetReferenceCount can be used on any component in any feature with any file extension you need to. In my sample I only use it on one.
ExFn_ResetReferenceCount will be the function that can called in a custom action.
2. Create a new Custom Installscript Action, function name will be "ExFn_ResetReferenceCount". Only use it in Install Exec Sequence, I selected "After RemoveExistingProducts" to make sure it will be executed at the very last.
What the script does, it loops trough all files within the given component, checks if there is a value in the ShareDLLs key. If there is a value, it will reset the count back to 1. Works perfectly in my case, as only one version of the application can be installed.