I have an program that used to uninstall properly and remove ALL files associated with it during uninstall. We have revamped our install/uninstall process to now use installshield.
With the previous install/uninstall process it was working just fine until about 2 weeks before we changes it, and still even now with he new installshield installers it fails to remove the .dll files upon uninstall.
I don't think the problem is with the installers themselves because we have the same exact problem with 2 very different methods.
Currently to make the uninstall process work we use control panel to uninstall it then delete the remaining .dll files manually
This problem happens to all the machines with these components and it is happening with all the components.
All machines had problems start at the same time.
with my installshield process i have verbose logging output to a .txt file, I do not know how would be best to display all the information in the files without it just being a massive dump.
Some of the reasons are:
The components were once marked permanent, or given a null guid. These are settings that propagate to the system. If you install with these set they stick to the the system and turning them off in the project won't change that.
Stein's answer - marked shared at install time. There's never a reaon to do this unless you know that a non-MSI install might install the same files to the same location (and set SharedDllRefCount) after your install.
There's also another shared bit, msidbComponentAttributesShared, and that tells Windows it's shared among multiple MSIs even if it was not in some of those installs. Very unlikely unless you are patching.
Running something like this VBScript to enumerate every component on the system will tell you if Windows thinks it's owned by an installed product:
Option Explicit
Public installer, fullmsg, comp, a, prod, fso, pname, ploc, pid, psorce
Set fso = CreateObject("Scripting.FileSystemObject")
Set a = fso.CreateTextFile("comps.txt", True)
' Connect to Windows Installer object
Set installer = CreateObject("WindowsInstaller.Installer")
a.writeline ("MSI Components")
on error resume next
For Each comp In installer.components
a.writeline (comp & " is used by the product:")
for each prod in Installer.ComponentClients (comp)
pid = installer.componentpath (prod, comp)
pname = installer.productinfo (prod, "InstalledProductName")
a.Writeline (" " & pname & " " & prod & "and is installed at " & pid)
Next
Next
Typically this relates to the flag Shared set to yes for the Components holding the dlls. This increments the SharedDLLRef
Count in the registry at HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\SharedDLLs
. Combined With Installshield bugs this can leave the file on uninstall. The solution is to set the component holding the file to shared = no and delete the entries in SharedDLLs
then try the uninstall again.
This sharedDLLs ref Count is a compatibility feature With non-msi installers and shouldn't be used in my opinion short of for files going to system32. MSI Reference Counts using the Component guids.
UPDATE: Enabling SharedDllRefCount sets the legacy ref-count here:
- 64-bit:
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\SharedDLLs
- 32-bit:
HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\SharedDLLs
Cleanup:
- Cleaning Up Your Shared DLLs Registry References for MSIs (untested by me).
- And some further MSDN suggestions for stranded components.
- Comprehensive explanation of reference counting errors.