MSI Failure to Uninstall - c#

I am sorry if this is a repeat but I cannot find what I am looking for by way of the Google (mostly because I don't know what to ask).
tl;dr - Is there a way to make my C# VS Installer project ignore any versioning errors or missing files of previous installs during updated version installs?
Long Version: I have created a C# application that includes 6 files (3 programs, 2 services, and a DLL). I am using a MSI deployment project in VS to create and distribute these files, register the DLL, and install the services. The problem starts when an anti-virus or malware app removes my files (and/or reg keys, services, etc.) from the system. In order to get a new version of my app installed, the MSI must be able to uninstall the old. At this point the install fails because the files or services have been altered and the original MSI package is required. Finding the original can be tricky as my clients typically do not keep them. There were also instances, when I did not know better, when a client needed a custom change to an executable. I would simply change the file and copy it to the users install folder. This further angers the MSI Gods because the file versions are now different than the ones that were put there by the installer. What can I do to easily remove old versions of my application and install the new? I am planning a Major revision and am expecting many headaches over a hundred or so installs otherwise. What else could/should I consider in the future to avoid these issues? What have I failed to comprehend?

Scope: Now that was a lot of questions at once. Firstly, how large is your distribution? How many machines are we talking about?
FixIt: You can try this FixIt tool from Microsoft as a "quick fix", but running that on many computers manually is cumbersome to say the least. Not sure if it can be automated. Never tried.
MSI Uninstall: An MSI does not normally need the original source to uninstall, unless it erroneously calls the ResolveSource standard action or a custom action does something strange. This old answer explains in more detail: Why does MSI require the original .msi file to proceed with an uninstall?
Major Upgrade Uninstall: It could be that during a major upgrade there is some source resolution going on - frankly I am not sure. Did you try to invoke uninstall by its own, manually? In other words run an uninstall command only, and not install the new version on top of the old one and do a major upgrade uninstall? I will run a test when I get a chance.
Section 3 here: Uninstalling an MSI file from the command line without using msiexec
How can I find the product GUID of an installed MSI setup?
Fresh Installation Location: As a workaround you could install your new version in a different place than your old version and de-couple it from the past versions. There could be conflicts in terms of COM servers and other global registrations, but if there isn't you can just leave the old version in place (potentially removing its shortcuts) and leave it there. Emergency "solution".
Self-Repair / Resiliency: MSI "knows" what you installed. It tries to actively maintain that installation state as explained here: Why does the MSI installer reconfigure if I delete a file?. Don't fight MSI - it fights back. Try to follow the paradigm - or you get a ride with the windmill :-).
Virustotal.com: One measure against malware inclusions or false-positive detection and file quarantine is to use an online service which scans your binaries with many malware scanners. Virustotal.com is such a service. Upload your finished setup and maybe also binaries there to see what different tools do to your binaries. Sorry if this is obvious, adding as a tip for whoever else reads this.
Bogdan Mitrache: https://www.advancedinstaller.com/antivirus-whitelisting.html
Section 7 in this answer: How do I avoid triggering MSI self-repair with my WiX / MSI package?
Links:
How to build MSI package on a linux server?
How do I avoid distributing sensitive information in my MSI by accident?
https://devblogs.microsoft.com/setup/resolving-prompts-for-source/
https://devblogs.microsoft.com/setup/resolvesource-requires-source/

Related

MSI Installing twice rather than upgrading with the same UpgradeCode

I'm using Visual Studio 2017 with the Installer Projects extension to make an MSI for my app.
However, when I run the, say 0.2.7 MSI on a system with 0.2.5 already installed, it adds another item to the appwiz.cpl, and leaves the version the same, so that after the 0.2.7 install, it just runs the 0.2.5 exe.
I make sure that the UpgradeCode is the same, the PackageCode and ProductCode are changing with each version and I have RemovePreviousVersions set to true.
My source code is available here. You'll find the installer project in ChromebookGUI/Installer/.
What am I doing wrong?
You can get a list of upgrade codes for installed packages like this: How can I find the Upgrade Code for an installed MSI file?
I have another one that is a bit simpler, but I couldn't dig it up right now. I will have a look later.
Adding this answer to "evolve" it if you provide more follow-up information (to avoid too many comments).
UPDATE: the other answer is here, but I wouldn't recommend that script if you have automatic logging enabled since it will create log files in the temp folder when run.

Application Installer: Microsoft database engine 2010 not available under pre-requisites

I have a windows form c-sharp application developed for windows 10. When I am trying to make installer, I cannot find "microsoft database engine 2010" (important for my app) under the "prerequisite" as shown below:
I do not want my customer to separately download it and install it. So is there a way I can generate an installer that will install complete software along with microsoft database engine 2010 ( if it is not already installed on the system) ?
I have never used this runtime, but did you do a Google search? It looks like the runtime is available: https://www.microsoft.com/en-us/download/details.aspx?id=13255. I am sure you did. Perhaps it is the wrong one? Or a format you can't use I guess.
The downloads are x86 and 64-bit versions in EXE format. The EXE files have embedded MSI files (Windows Installer) that you can extract, or you should be able to just run the EXE in silent mode (probably safest). Do a AccessDatabaseEngine_X64.exe /? to get a list of parameters.
Merge Modules
Normally you can use a merge module to add a runtime component to your own MSI at compile time, but this runtime may not be available in this format. Instead you can use a bootstrapper of some kind to run your own MSI installer and this prerequisite database engine runtime MSI / EXE in sequence (or even just a batch file - see towards the bottom).
Bootstrappers
The WiX toolkit (which is a better way to make MSI files than Visual Studio Installer Projects - see the link for some details) features a bootstrapper called Burn - it can install both EXE and MSI files in sequence. There are also other bootstrappers available, but I haven't tried them. Here is a description of some bootstrappers from earlier: Wix - How to run/install application without UI.
As you will see in the link immediately above, there is a sample of the WiX bootstrapper Burn in use here: https://github.com/frederiksen/Classic-WiX-Burn-Theme (it even shows a WiX MSI package as well). WiX and Burn does have a learning curve.
There may be simpler options available using Visual Studio Installer Projects that I am not aware of, but I think you need a bootstrapper to install several MSI files in sequence. As far as I can see these Installer Projects support only the listed prerequisites that you show in your screenshot to download and install on demand, and they seem to allow the addition of (any) standard merge module. It is very strange that you can't tell the Installer Project's setup.exe to kick off the install of any MSI as a prerequisite considering that the whole feature is made to install prerequisites in the first place. PhilDW will surely be able to tell you with certainty.
Commercial tools such as Advanced Installer or Installshield also have features to allow you to bundle setups, in various formats, together for installation in sequence. It might be a feature in the Premium or most expensive edition in Installshield's case. Not sure for Advanced Installer. Bogdan Mitrache will be able to tell us - they may do it better. I don't want to claim something I am not sure of - things like these change as new versions are released (may obviously also be the case for Installshield).
Batch File, PowerShell Script
In closing I should add that you can obviously use a batch file to install files in sequence (or a PowerShell script - which would depend on .NET though). For example wrapped in a self-extracting archive. You can quickly try the built in iexpress.exe self-extracting tool in Windows: Hold down Windows Key and tap R, enter iexpress and press Enter. Click through the options. Be very aware of the security vulnerabilities iexpress suffers from!
Not sure how well well these wrappers clean up their temporary files (particularly if there are errors during installation) - which could be ugly and annoying, but it should work. A bootstrapper can do a lot more though - such as provide a real GUI for your users and handle error conditions among other things.
Security problems with deployment solutions is a pet peeve of mine, so I want to add a link to this: Prevent DLL Hijacking Burn with Clean Room. A WiX Burn issue fixed in the latest version of WiX (as of Jan.2018). As you can see, the allure and simplicity of iexpress.exe generally does not make up for its security shortcomings. It is most definitely not good enough for a world-wide, large-scale, public release.
Should you want to use a batch file or PowerShell for the installation, then the following answer provides some information on using the msiexec.exe command line, and there is also a link to another answer which deals with PowerShell installation: How can I use powershell to run through an installer?

Is it possible to check which MSI packages depend on a specific package?

As in title, when I have some MSI package, is it possible to see which other packages depend on it? If yes, how?
If that's not possible, is it at least possible to tell Msiexec to uninstall all depending packages as needed?
In short: yes and no. I guess. Several MSI files can be installed in sequence without there being any reliable way to tell if they are actually related as products, but they can also be bundled together by various mechanisms so they can install as a "single unit" (suites or bootstrappers, see below), but they still might not be "tagged" as belong together after installation.
Bundling MSI Setups Together (Launchers, Bootstrappers, Suites)
Commercial tools such as Installshield have "setup suites" I think they are called. I believe they can even have a single entry in Add/Remove Programs, but that I am not sure of (we don't always have access to all the latest versions of commercial tools).
WiX - the open source framework for delivering MSI files - has a feature called Burn (and maybe even other mechanisms that I am not up to speed with). It allows you to run several MSI files in sequence with a launcher GUI.
There are also other solutions, or bootstrappers as I call them (here is one, untested by me), for installing MSI files in sequence or rather for installing prerequisite runtime components.
People can also roll their own launchers or installer GUIs that run MSI installers or other install types "under the hood" in whatever sequence desired. The installer for Visual Studio comes with such a GUI where you can select different packages to install.
The point is that by running these launchers and checking what they install you can get an idea of setups that "belong together". Check the vendor download site and see what is included in the bundle.
Related MSI Setups (Upgrade Table and Installation Location)
There are also some other clues for when MSI files relate to each other. The "Upgrade table" inside an MSI will specify related products (and hence related MSI files that were used to install them) that are to be either detected only or detected and uninstalled as part of the installation of your new MSI file. This is part of the upgrade mechanism of Windows Installer and is referred to as a major upgrade. There is a great deal of flexibility in this table, so that you can detect product and not uninstall them but continue, or you can detect products and refuse to install (for example if a higher version MSI is found installed). Note that the upgrade table generally does not detect other, related products (though it can), but rather different versions of the same product that are to be upgraded as part of the major upgrade operation. As a technical tidbit I added a section below on how to find all related product codes for a specified upgrade code.
Finally, and this is perhaps the easiest "clue" - you can check the MSI's primary installation location under the ProgramFilesFolder hierarchy. This location will normally feature a company name and a product name along these lines: ProgramFilesFolder\Company Name\Product Name - and you can add to that potentially a major version name. MSI files installing to the same Company Name folder would likely be related.
And check towards the bottom of this answer for a possible way to use the "Install Date" of MSI packages to determine what packages installed at the same time (indicating being related). Likewise the "Manufacturer / Publisher" for the MSI file can indicate "common descent". As can potentially the "Install Source" as well (the location on disk from where the install originally ran or was initiated).
I hope this answers your question. As Urman indicates, it is difficult to tell what prerequisite packages are needed for an MSI that was installed, but you can use dependency scanners to determine what runtimes the main application binaries have to get a clue. It all depends on what your problem really is and what you are trying to figure out.
Merge modules, which Urman mentions, are compiled into each MSI - a form of static linking I suppose - and you can hence see that this prerequisite is needed for the MSI that has it embedded.
Technical Tidbit: Finding Related Product Codes
You can find all installed MSI files that share the same upgrade code by running the following VBScript. You must input a valid upgrade code (found in the property table of the MSI you want to find related products for).
The actual MSI API call is Set upgrades = installer.RelatedProducts(upgradecode) - the rest of the code is supporting structure. A sample upgrade code you can try might be {AA783A14-A7A3-3D33-95F0-9A351D530011} - Microsoft Visual C++ 2008 Redistributable - x86 9.0.30729.4148 (if you have it installed). It is one of 3 related MSI packages, so you get 3 product codes back - provided the package is installed in the first place:
Dim relatedproductcodes, upgradecode : relatedproductcodes = "No related product codes found"
Dim installer : Set installer = CreateObject("WindowsInstaller.Installer")
upgradecode = InputBox("Please paste or type in the upgrade code you want to find all related product codes for." + _
vbNewLine + vbNewLine + "Upgrade codes are found in an MSI's Property table, if it has been defined.", + _
"Find Related Product Codes:")
If upgradecode = vbCancel Or Trim(upgradecode) = "" Then
WScript.Quit(0)
End If
On Error Resume Next
Set upgrades = installer.RelatedProducts(upgradecode)
If (Err.number <> 0) Then
MsgBox "Invalid upgrade code - aborting.", vbCritical, "Fatal error."
WScript.Quit(2) ' Following exit code "standard" from MSI SDK automation samples
End If
If upgrades.Count > 0 Then relatedproductcodes = ""
For Each u In upgrades
relatedproductcodes = relatedproductcodes & u & vbNewLine
Next
MsgBox "The related product codes for the specified Upgrade Code: " + vbNewLine + vbNewLine + relatedproductcodes
I doubt this will do much for you, I just figured I'd show you how in case it is useful. If it is, then I have a more comprehensive script for my own use which will generate a whole list of MSI pertinent information as a html export - including related product codes.
UPGRADE: In fact, looking at such an html export I can see the "Install Date" list showing pretty much the installation order for every MSI package on the box - which is another indication of packages that installed together and hence can be related. It should be noted that this date is not necessarily the original date for the install, but its latest "modify operation". So it can't be relied upon.
Sample output:
No to both. Windows Installer tracks dependencies on packages to components, but nothing between packages. In some cases you may be able to infer package-level dependencies, for instance by reading system searches, but there's nothing native to Windows Installer here.
This is part of the reason you see some tension between people who recommend installing the Visual C++ run times as a separate .msi (or .exe) and those who recommend installing it by incorporating its merge module. The former is much easier to reason about, but only the latter will do proper reference counting of packages that depend on it.

Visual Studio 2008 Deployment Project Issues?

I have created a successful deployment project using Windows Fourms that work as intended but there are two things that need to be solved:-
First: I have to click the setup.exe file in order for the installation to check for the perquisites, and if click the setup.msi it proceeds to install the software directly without checking anything.
Second: When i click on the setup file while the software is already installed on my PC, i get an error message "Another version of this product is already installed. Installation of this version cannot continue. To configure or remove the existing version of this product, use Add/Remove Programs on the Control Panel" while i should get a Repair and Remove options.
Can anybody help me solve this problems ?
As said by Morten, that's how it works. You want to make sure that the prerequisites are (get) installed before your product is installed.
This probably is caused by a rebuild of the deployment package after you installed it. Windows installer notices that you use a different MSI (with a different package code), that contains the same product version. This situation, apparently, is inconclusive enough to leave it up to you what to do with it. The logic of this, I think, is to prevent a "Repair" that in fact installs a different product. Inconvenient for testing, but very much desirable in production environments. If you try to install the same MSI you should get the repair/remove options.
BTW, after building a release, you can right-click the setup project in VS and choose "install". This executes a setup that kindly removes a previous installation with the same version.

.NET Setup Package Installer

I have a .NET 3.5 Setup Package Project which installs my application successfully.
The setup package deploys a number (around 70) custom files for use from within the application.
From time to time I have the requirement of deleting some of these files, however upon restarting the executable, it automatically runs a portion of the Setup MSI again, and re-installs these files.
The only way I can achieve my desired result at the moment is to delete the files after starting the executable.
I have looked through the attributes on the files in the setup package such as Vital and PackageAs, however cannot seem to identify the required setting to achieve this.
Does anybody have any idea what is needed to acheive this ?
Much thanks
From http://msdn.microsoft.com/en-us/library/kz0ke5xt%28v=VS.100%29.aspx
"
How do I turn off repair for a file that users are expected to modify or delete?
Visual Studio creates advertised shortcuts so that when the program is started it verifies that all its files exist. To change this behavior and cause it not to repair the file, select the files in the setup project and change the Condition property to NOT REINSTALL so that the file will not get reinstalled on a repair and its Transitive property to TRUE so that the condition is re-evaluated. This will cause the Installer to flash on the screen the first time after the file is deleted, as it verifies that the file should not be reinstalled, but you will not see the installer after that.
"
This has annoyed me too, and I don't know the specific setting you have to change to prevent this, but I can tell you a work-around that I've used. I found that it only happens when I run the application from the shortcut that was installed as part of the installation. So, if you create a new shortcut to the application and run it via that shortcut, then the files you've deleted won't be automatically restored.
Windows Installer supports three types of product upgrades: major upgrades, minor upgrades, and small updates. A synopsis of which upgrade to use under what circumstances can be found here: http://helpnet.flexerasoftware.com/robo/projects/installshield12helplib/MajorMinorSmall.htm
What you want to do is set you installer up in such a way that the new version of your software sees the file deletions as upgrades to a prior version. If you fail to do this and then you delete files, the program installation thinks it is damaged, and tries to restore the files you deleted when the program is executed again.
In InstallShield (the installer product with which I am familiar), there is a Product GUID and an Upgrade GUID. The Upgrade GUID always stays the same within your product family of different versions. The Product GUID changes with each new MAJOR or MINOR release. In general, if you follow this pattern, and then specify file deletions in your new version, the installer should interpret the file deletions as upgrades, and you should not get any errors on subsequent execution of the newly-installed version.

Categories

Resources