I have an MSI installer that registers a DLL. I also want to give the users the option to manually register the same DLL (could be different version). Consider the case where the user first installs the MSI, then manually registers the DLL (using regsvr32). The previous file is overwritten.
When I uninstall my initial MSI, the overwritten DLL is also removed. Is there a way I can prevent that from happening in case the first DLL has been overwritten.
You could use the FileSearch element of WiX and, if the DLL with this version is found, set a property accordingly. You could then use this property to decide if the DLL should be unregistered or not.
I guess for checking if the user registered it manually or not you have to save that information during installation, e.g. somewhere in the Registry. You could then also do a RegistrySearch for this key.
You probably also have to set the Permanent-attribute of the component and then remove it by yourself (depending on the property set above).
You could ship that other Dll in a separate MSI, making sure it's installed to the same location and has the same component guid. That would result in Windows knowing about it being shared, and uninstalling one MSI would not remove the remaining Dll because of that sharing.
Without knowing your exact situation it's hard to know if that will work. If you always ship a higher version than than the one in your current MSI then it will work. If you try to replace that Dll manually with a lower file version then repair will restore the correct higher version from the original MSI, so you're already in potential trouble. The only safe way to maintain files installed with MSI is with another MSI-type update, like a patch, major upgrade etc.
Related
I am trying to find any information how the Windows installer cache is working for Wix Bootstrappers.
For MSIs you do not follow any special rules to be sure a MSI will be cached by Windows. For Bootstrappers (Burns) it looks the same, but I had several issues trying to uninstall the package without original installer.
For me several points are not clear:
how to uninstall a product without original .exe installer?
will .exe installer be cached by default during installation?
does custom user interface affects Windows caching rules for .exe installers?
If you go into your registry and find "Computer\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall", you should be able to find a registry key corresponding to your installer package. There should be one for the bundle itself and one for each .msi installed as part of the bundle. If you find the correct key for the bundle, it will have a value called "UninstallString". This is the string you should use to manually uninstall the package via the command line.
For your second point, Windows automatically caches installed burn bundles. The same registry key you found in the step above will have another value called "BundleCachePath", which should point you to the location of the cached .exe file. This should be under "C:\ProgramData\PackageCache{GUID}", where {GUID} is the package GUID of the bundle.
I can't see why having a custom UI would change the caching location, unless you manually add a dialogue to do so.
I created a WiX-based installer back in the WiX 3.5 days. The documentation then was even worse than it is now. To make matters worse, it was my first installer—so I didn't do everything right.
Some background: the installer installed two applications and a driver (each of these were a separate feature consisting of one or more components). One of the applications in question is a vendor-proprietary device configuration application written in VB6. Since it's a VB6 application, it uses the libraries comctl32.ocx and tabctl32.ocx.
The crux of the problem is that I didn't see these two libraries in the %windir%\System32 folder on Windows Vista (and/or Windows XP? I don't remember, it's been years since I first wrote this installer). So I thought I needed to install these two libraries along with all of their requisite COM registry entries. (I ended up installing the COM libraries in my application's folder—as you would for a private assembly, but registered them globally in HKLM.) As much as I read about things when creating the first installer, I never once came across the fact that, as of Windows XP, COM components could be installed side-by-side. (And even so, why didn't I use the MSI tables Clsid, ProgId, etc.—which granted, today, is frowned upon, but it would at least have been more correct than what I did? But I digress; what's done is done in MSI land.) Anyway, when creating the original installer, I used the following WiX markup for creating the COM registry values:
<RegistryValue ... Action="write" />
I also should mention that at the time, I had not come across any sort of 'Component Rules 101' kind of documentation as I have this time around. So, this MSI does not follow the component rules. The MSI contained one component for each COM library and its associated registry values with the COM library being the KeyPath of its component.
The question is, if the registry keys/values existed prior to my original MSI running and installing the first version of my product, will uninstallation cause these keys/values to be removed from the system? (I assume these keys/values were created during Windows setup—so are they already reference counted?) I don't want to possibly break other applications on a users' system that relies on those libraries.
If the answer to the above is yes, then my current plan to rectify the situation is:
Author a new MSI as a <MajorUpgrade />—afterall, I am performing an upgrade.
Provide the COM registry entries that were in the original installer for the comctl32.ocx and tabctl32.ocx COM libraries—I'm guessing that I would need to do this with a CA (or multiple CA's) so that they don't get removed again on the next upgrade. I see one of two ways of accomplishing this:
Directly create the registry entries taking care to ensure the values match those of a fresh windows installation (appropriate to the version of OS on which the installer is executing)
Dynamically add the registry entries to be created to the MSI Registry table (which if I understand correctly, isn't tracked by windows installer in terms of uninstallation?)
If previously existing registry keys overwritten by MSI are removed on uninstallation, then:
Is my proposed solution acceptable?
Which of the two options for replacing the removed registry entries is best?
If neither of those two options are acceptable, does anyone have any other suggestions on how I might rectify the situation so as not to break other applications that (may) rely on the libraries in question?
It was a long read but I think this is what you are looking for:
ICE09
To quote the beer commercials.... I don't always install files in the SystemFolder but when I do, I make them permanent.
First, thanks to Christopher Painter above for responding to my question; though, it's not really an answer in the sense that I'm looking for—fixing an existing installer that's "out in the wild". Though, in his last comment about a minor upgrade, that might work for some people.
Next, thanks to Aaron Stebner who responded to my e-mail requesting guidance on this same issue. His advice is to author a MSI component which has no ID. By authoring such a component into a MSI, the component is not tracked by MSI; essentially, it becomes a permanent, uninstallable component. This might work in this situation, if it were completely necessary.
However, after doing some research, I believe that there isn't much risk to damaging a user's system by removing the registry entries I outlined above.
I loaded a fresh copy of Windows XP SP3 and Windows Vista SP1 into a virtual machine. Out of the box, neither of these versions of Windows have the COM components in question registered in anyway in the Windows registry. This makes sense, since from Windows XP onward, there has been registry-free COM registration. This also continues to be the case for Windows 8.1—again, this was expected.
The worst that could happen if these registry keys are uninstalled is that some other older piece of software on a machine that relied on such registry entries could end up broken (e.g. this software is from the late-90's to early 2000's era and used a non-MSI installer and/or installed the COM libraries globally—which they shouldn't have done in the first place—just like I shouldn't have done in the first place ;) ). At that point, the user can either re-register the COM libraries using regsvr32.exe or repair/reinstall the application in question. The likelihood of such applications existing are slim to none in this day and age.
i have already an installer for our application. but it is exe-file. it was created many years ago.. application of course was updated. we used a bat-file to register new dll-files and to install our service(windows). but we want to do all this by installer not a bat-file. we chosen a wix techology. i read about <Patch> node, but to use it i need an msi from previous version.. i think to do a simple installer, that will stop service,copy and register dll in the installed application's directory, install service. but i don't know will it overwrite the files without any problems?
You can only create an MSP (Patch) for an MSI (Installer). Also, you're going to run into component ref counting problems if you install your components into the same directory as the original install. The problem is MSI will go to see a file is already there, make it as a shared resource and increment the usage counters. Then on uninstall it will decrement, see that it's not 0 and remove to uninstall the files.
I'd suggest installing to a new directory and then using the RemoveFile table to get rid of the old files. Also I'd suggest following good CM / Versioning practices so that you don't have to worry about hacks such as Version Lying.
If all your application just needs to xcopy files, setup a directory and maybe even a ShortCut, it should be a piece of cake.
Versioned files like executables will automatically be overwritten if the version of the file number is lower.
See also Copy if not exist in WiX.
I've developed a Wix installer for an internal project however entirely by accident I've found that I'm unable to uninstall the installer on my development machine as I get the following error message:
The feature you are trying to use is on a network resource that is unavailable
with a dialog pointing to the path of the .msi that I installed from feature from. (The .msi is there, however is has been rebuilt and so has changed since I installed it)
I'm concerned by this dialog as I had believed that Windows Installer kept track of installed .MSI files, however this dialog seems to suggest that I can break my uninstaller by deleting, moving or changing the installer.
Is this the case?
What do I need to do to make sure that I don't break my uninstaller in this way? (Do we need to keep copies of all versions of the installer ever installed on a machine?)
The easiest way to get out of this situation is to do a recache/reinstall. Build a new version of your MSI that isn't "broken" (in whatever way it is broken, in this case, it might not really be broken at all, you just need a new source). Then you use a command line like:
msiexec /fv path\to\your.msi /l*v i.txt
That will copy your.msi over the MSI that is cached and do a repair. Then you'll be in a better place.
One of the first painful lessons of writing installs is to never run your install on your own box. Certainly not until it reaches a point of maturity and has gone through several QA cycles. This is what we have integration labs and virtual machines for. (There is a saying about things you shouldn't do in your own back yard.)
That said, normally an MSI uninstall doesn't require the MSI but there are situations where it could be required. For example if one was to call the ResolveSource action during an uninstall, MSI would then look for the .MSI.
Now there are several ways out of this pickle:
Take an MSI you do have and edit it with ORCA to match to file name, UpgradeCode, ProductCode and PackageCode of the MSI that you installed. You should be able to get all of this information from looking at the stripped cached MSI that exists in %WINDIR%\Installer. CD to that directory and do a findstr -i -m SOMESTRING *.msi where SOMESTRING is something unique like your ProductName property. Once you know the name of the cached MSI, open it in Orca to get the required attributes. Then put these attributes in a copy of the MSI you have available and try to do an uninstall. No, it's not the exact MSI that you installed but usually it's close enough.
or
Use the front end windows installer cleanup utility (if you still have it) and/or the backend MSIZAP utility to wipe all knowledge of the application from MSI and Add/RemovePrograms. Note, this doesn't actually uninstall the program so you'll have to also write a script or otherwise manually uninstall all traces of the program.
or
Reimage your workstation
If you know exactly what is wrong (which is often the case during development), I prefer to open the MSI file that Windows will use for uninstallation and edit it directly with a tool like Orca to fix or remove the part that causes the failure.
For example:
Locate the MSI file in %WINDIR%\Installer. The MSI should be the last edited MSI file in that folder right after you did the failed uninstallation.
Open the msi file with Orca.
Remove the failing part - for example the InstallExecuteSequence action that fails which is atypical scenario.
Save the msi and close Orca to release the lock on the msi file.
1 - Have you experimented with "run from source" during installation?
This is an option in the feature tree which allows you to run some files from their installation source. This is generally combined with an admin image on the network. See image below. I haven't tried it, but I assume this could cause: "The feature you are trying to use is on a network resource that is unavailable" if the network is down and you are trying to uninstall. Just a theory, there are other ways this could happen.
2 - Are you running script custom actions? If so, do you extract to the tmp folder or run from installed files or the binary table? If so, is the custom action conditioned to run only on install?
3 - Are you perhaps running an EXE custom action that is pointing to an installed file? If so this file may be unreachable on the network.
4 - Are any of your userprofile folders redirected to a network share?
5 - Are you installing anything directly to a folder on the network?
There are plenty of other possibilities.
One of our applications needs to register a COM control during installation. If a newer version of that control is already registered, we don't want to overwrite it with the older. What are the Windows MSI install conditions I would user to control this? Or is there some other 'best-practice' method I'm not aware of?
Thanks
Sounds like your main problem is that you have two controls that support the same CoClass's, but live in different file paths. That's not a great situation to be in. If at all possible, there should only be one possible file path for a binary that implements a particular COM class.
That way, file versioning rules will make sure that the latest file is installed by MSI installers. MSI won't by default overwrite newer file versions with older ones.
There are applications out there that have the problem that customers need to use the older version of a class occasionally while still having the newer version installed and available. One solution is to have a utility application that the customers can run that will "point" the COM registry entries to the correct binary.
There are definitely permissions issues with implementing that correctly on non-administrative accounts and you should avoid putting yourself in that situation if at all possible.
If you absolutely must have multiple binaries implementing the same COM CoClass GUID and if it is not too late to change old clients, you could create a master "factory" class that takes whatever data/info is available from the client and chooses the correct implementation to return. It would simply be a COM class with an interface that had methods that returned interface pointers to the actual interface the clients needs after allocating the proper implementation class and queryinterfacing for the client interface.
edit
You may choose to change the location of your application from version to version (e.g. "c:\program files\My App V2". That's okay so long as you use the MSI product code and version #, etc. attributes of your packages to force MSI to uninstall any existing versions of your application before installing new ones.
What you are missing here is merge-modules. Basicly you create a merge-module for your COMxx component. This gets recompiled with each new version 19, 20, 21, ... of your component (but keeps its GUID). Both your applications "reference" this COMxx merge-module and ship its content to the user.
This way windows installer will make sure your dll is refcounted and upgraded only if needed, provided you maintain (increase) version info in your dll.
Edit: The merge-module also hard codes install path, which usually ends up somewhere in C:\Program Files\Common Files\{My Company}\{My Component}, both applications ship it there.