Uninstall an MSI with msiexec fails with new version of MSI - installation

We are installing several web sites using msi's as part of continuos integration tests.
For each build we want to uninstall the old msi and install a new one.
Problem is we do not have the old msi after the build server has done a get latest and rebuilt the system.
Is there a way in which we can uninstall the msi without having access to the orginal msi?

Yes you can, if you know the product code. Just type
msiexec /x [ProductCode]
on the command line. Or you could do it through the Add/Remove programs applet.
If you want to find the physical file, Windows actually stores a copy of the msi when it runs it - you will find it somewhere in your %WINDOWS%\Installer folder, but it will have been given a random name so could be quite hard to find :)
Alternatively if you don't know the product code (which you should) then try searching for your app name under the HKEY_CURRENT_USER\Software\Microsoft\Installer and HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData registry keys, you will find the product code there. (quick hint: you can also search for UninstallString values in the registry).

Related

Uninstalling msi via msiexec fails with a 'only valid for applications installed' message

We have a legacy software installation that we're trying to remove from our organisation. We have different versions and are trying to create a universal uninstaller for all versions. We've come across a particular release that doesn't seem to be able to be uninstalled via command line though. And it's proving difficult to create a workaround.
I've found the GUID of the application in the registry via
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
And the command I run is:
msiexec /x {080FDF44-6D15-4D2E-977E-74D5168198E7}
I get an application prompt asking me if I want to uninstall the product, so I click 'Yes'. And then it looks like it's starting but never actually does anything. So I dug round the registry and found another GUID in:
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\Userdata\S-1-5-18\Products\44FDF08051D6E2D479E7475D6118897E
If I run the same command as above with the different GUID, I get the application confirmation box asking for uninstall then after clicking OK, I get an error saying:
The installation package could not be opened. Verify the package exists and you can access it.......
I've been into C:\Windows\Installer into the folder with the above GUID and all that is in there is an icon and an *.mst file. In the root of C:\Windows\Installer, there is an *.msi called the same product in the details but with another version ID of:
8A2C4F93-4B31-4474-B9F2-2E51BF5D71A8
If I run the msiexec against that ID then I get a confirmation box again then another error which says
The action is only valid for products that are currently installed.
If I run the uninstaller, it uninstalls fine from the programs and features and uses the generated *.msi for the uninstalled (e.g. C:\Windows\Installer\241a6.msi and matches the product ID of 8A2C4F93-4B31-4474-B9F2-2E51BF5D71A8). This will change form machine to machine. Any other ideas on how to get this off in a neat and managed way?
You can't dredge the registry for ProductCode guids because they are obfuscated. If you don't really know the ProductCode, then look at ways of enumerating installed products. For example, the direct C++ way is MsiEnumerateProducts, and C# pinvoke equivalents, something like this:
MSI Interop using MSIEnumRelatedProducts and MSIGetProductInfo
Then you will get the actual ProductCode and can get other info with it.
If sometimes it doesn't work when you are absolutely sure of the ProductCode, then it was perhaps installed in a per user context that's different from the one you're running the program with.
Also, for MSI-installed products Windows doesn't use the uninstall string, it just uses the ProductCode directly. Again, registry dredging is not the right thing when there are actual APIs specifically to enumerate installed MSI products.
If an uninstall requires access to the original MSI that it was installed from, then there are at least two reasons:
The MSI has an unconditional ResolveSource action that forces it to ask for the oroginal MSI file.
The cached version of the MSI file has been removed from C:\windows\installer.

Error 1001. Exception occured while initializing the installation

I am seeing the following error while trying to uninstall. How can I uninstall the software when there is no folder WRT the software in the program files.
Note: I have deleted the software folder from program files.
Error Message:
System.IO.FileNotFoundException. could not load file or assembly or its dependencies. the system cannot find the file specified.
I need the solution on how to uninstall the software when there is no folder existing the program files.
Sounds like a very britty InstallUtil custom action that has a dependency on a file being installed with no exception handling if it's not found. Awesome! :)
Take the orginal MSI that you installed and edit it with Orca to remove the custom action from the InstallExecute sequence. Recache the MSI using the command:
msiexec /i FOO.MSI REINSTALL=ALL REINSTALLMODE=vomus /qb
Finally uninstall the application.
Broken Uninstalls: There are a few ways to approach this such as 1) trying to run the repair sequence of the installed MSI which might be able to pull files down from the original installation location or 2) run the original installer itself again - as in the install sequence rather than the repair sequence (must be the exact MSI file used to install the software originally), etc... These approaches are all vulnerable to failure and generally need some "hacking" to succeed.
Microsoft FixIt: This all leads to the recommendation of the last resort solution that is "sort of official", it is the Microsoft FixIt tool. It can be used to clean out broken uninstalls by "unregistering" the installation rather than running the actual uninstall for it. It should work. Never use it if you don't need to, there are risks.
Logging & Debugging: The above should work, but here is information on how to log an MSI operation: Different ways to create and interpret MSI logs to narrow down the cause of the problem seen.
Links: Below some general-purpose MSI uninstall resources. The first link lists cleanup strategies for broken uninstall - very hacky some of it. The second link lists different ways to invoke uninstall of MSI files - there are a lot of ways:
Broken Uninstalls: Here is a generic list of cleanup approaches for broken uninstalls - most of this is very hacky, only use this if you really need to.
MSI Uninstall Approaches: Uninstalling an MSI file from the command line without using msiexec.

Windows Installer - force users to remove via Add?remove Programs

We have an installer solution written in Visual Studio 2005 Installer; that calls a C# custom action and we have hit a known issue, regarding the fact that on an upgrade - the old install code is run and not the new code, because Windows is running a cached version of the custom action dll. We know this and although not over the moon about it - we have moved on.
When we release a new version of the installer and a user runs it, we now want it to check to see if an ealier version is installed - if there is one; we want to display a message telling them that they have to remove the old version via Add/Remove Programs. We know if they do a manual uninstall followed by an install, then all is fine and dandy - BUT it doesn't matter how many times we tell our users, via documentation; that this is what they have to do - they will still try and just run the new installer, without removing the old version first.
Therefore, we would like to put up a message and thus force them to to what they are told !! I've seen some installers do this ( though of course not sure what installer package was used to create these ). We only have VS 2005 and of course orca !!
Cheers,
Chris.
This can be done through a custom launch condition:
create a search which determines if the old version is installed (you can search for a component, registry entry or file)
use the search property as a custom launch condition
For example, if the search property is OLD_VERSION, the launch condition can look like this:
Condition: NOT OLD_VERSION
Description: An older version was found. Please uninstall it using "Programs and Features" in Control Panel.
When OLD_VERSION property is set to a value (an older version is found), this launch condition will show the message and stop the install process.
This doesn't quite make sense. Have you remembered to change the package GUID in your new setup? The package GUID identifies a specific setup file, and if two MSI files have identical GUID they will be treated as the same file regardless of whether they are or not. This could trigger a cached version of the MSI to be invoked and all sorts of hell breaks loose.
I would recommend reading up on "major upgrades" which will allow automatic uninstall of the existing version before the new version is installed. You also need to make sure you understand the basics of the technology before deploying to the wild. You must NEVER use identical package GUIDs for any MSI files. It's practically always wrong, and will lead to very mysterious problems.
I can't write up the whole major upgrade solution here, but basically it involves authoring the "Upgrade" table of your MSI to detect versions to uninstall. You need to change the package code, product code and version number (only 3 digits matter) and keep the same upgrade code (two MSI files with the same upgrade code "know" they are related - i.e they are from the same product family). Check MSDN for samples of major upgrades.
NB! If you have deployed MSI files with duplicate package GUIDs to your developer machine, it could have stray installs that must be cleaned up with MSIZap or similar. Use caution, or better yet test your new installer on a clean test system. Developer systems are full of junk and not generally good for MSI testing.

Uninstall without an MSI file

I often get a problem with Windows Installer trying to uninstall a package, but it complains that:
The feature you are trying to use is on a network resource that is unavailable.
Is there a known means of uninstalling such packages when the original MSI is simply not available?
Please note that Microsoft has now released an official tool to resolve these issues, without the problems that previously existed with MSIZAP.
Microsoft Fixit: Fix problems with programs that can't be installed or uninstalled
Take a look at a tool called MSIZap released by Microsoft.
UPDATE:
MsiZap.exe has been deprecated for quite some time. Its use is unsupported on all recent versions of Windows, and it is considered a very unsafe tool to use.
I added a link to a newer Microsoft support tool designed to clean out installations, but this tool also appears deprecated at this point. I have removed the link from the comments section.
Perhaps try the tool linked to in saschabeaumont's answer below.
FYI, this post explains the root problem https://superuser.com/q/293542/245923
You can uninstall it using the product code:
msiexec.exe /x {your-product-code-guid}
You would obtain this code from the MSI itself, or whatever tool you are using to build the MSI.
Note that when you uninstall a product, it uses a cached MSI, since only the original MSI knows how to uninstall itself. When you use the product code, it uses the cached MSI from C:\WINDOWS\Installer.
Update, Stein Åsmul: There is a whole list of cleanup approaches here (recommended).
UPDATE:
This newer support tool can be tried on recent Windows versions if you have defunct MSI packages needing uninstall. This new tool appears to have been deprecated as well.
Perhaps try the tool linked to in saschabeaumont's answer.
It is not normal or standard MSI behavior to ask for the original source media - it indicates a badly designed MSI package. If you experience this with a vendor MSI it is highly recommended that you report the problem to their support team. Here is a more comprehensive explanation of the problem: Why does MSI require the original .msi file to proceed with an uninstall?
In most cases MSI packages can be uninstalled from add/remove programs from the control panel even if you don't have the original installation database for the MSI - the uninstall is run from a cached copy of the original MSI in the system folder %SystemRoot%\Windows\Installer (in some cases this cached MSI could be missing, see section 12 here for potential causes).
Earlier versions of MSI tended to trigger this problem (asking for the original installation media) more often (Office back in the day), and legacy MSI files can still cause uninstall problems that can only be solved using the msizap.exe tool (this tool is deprecated, outdated and no longer supported). This command line tool (msizap.exe) also had a GUI available (MSICUU2.exe), both tools are deprectated (try the link to the new cleanup tool listed above).
Just for the record: If you have access to the original MSI that was actually used to install the product, you can use this to run the uninstall. It must be the exact MSI that was used, and not just a similar one. There is a unique package guid assigned to each MSI file, so Windows will know if it is the right one.
Related answers:
wix - custom action dialogbox on silent uninstall of application
Uninstalling an MSI file from the command line without using msiexec
You didn't do something crazy like go to C:\Windows\Installer\ and delete the files in there did you?
One drawback of MSI files is you need the complete MSI file in order to uninstall or repair the application. Windows loves to store a copy of the MSI. It also renames the MSI file from a common name to a GUID with no table (that I can find) to map original names (example: Office2010.msi) to the new GUID so you have a PC with many GBs of wasted space that you can't delete. A machine that's not even 1 year old can easily hit 8 GB (example: mine).
There is an MSI cleanup utility from Microsoft, Windows Installer Cleanup Utility (deprecated tool, unsupported and unsafe to use - perhaps try this answer instead: Uninstall without an MSI file).
Or CCleaner can usually do this
Control Panel --> Add/Remove programs?
EDIT:
Your post mentions nothing about using add remove programs to uninstall the app, you said the "Windows Installer" (MSIEXEC - see the link below), which is not the same thing.
http://msdn.microsoft.com/en-us/library/aa367988(VS.85).aspx

MSI Bootstrapping: External URLs

Much searching has lead me to find several descriptions of how to create a bootstrapping msi, but these solutions all assume the msi is local or a standard Windows component. Is there a way to make an msi that downloads an installer (which is also an msi) with normal MSI or Wix code rather than by having the bootstrapper execute some non-native program to do so?
My experience with msi's has been it's not possible to run 2 at the same time. (could be wrong though)
What I ended up doing was to instead make an installer exe using Inno Setup (http://www.jrsoftware.org) and ISTool (http://www.istool.org) which downloads and installs the various msi's. With ISTool it's very easy to do.
I know it's not as chic or sexy as Wix, but it worked for me very well.
I would create a custom action that runs in the InstallUISequence. This would download the MSI if necessary (to the source folder), and then try to launch it as a nested installation.
Windows prevents two installs from being in the InstallExecuteSequence at the same time, so if you're looking for a silent install solution with a bootstrapper, you're SOL.
However you can start another install from the UI sequence, which is probably an OK solution as long as you advise your customers that certain other dependencies must be installed first if they're going to deploy via group policy or some other 'silent' method.
If it helps, I'm pretty sure you can also call MSIEXEC with a URL, eg. msiexec.exe /i http://some.domain/blah.msi /passive
I would suggest that you write a native app and have it run the first msi and then run the seccons msi. I wrote a blog on how to do this. Here is a link (http://blog.foldertrack.com/?p=45)

Resources