2

I launch msiexec in another process and wait for exit:

var p = new Process
{
    StartInfo =
    {
        FileName = "msiexec",
        Arguments = string.Format("/i \"{0}\" /qb", @"c:\install\setup.msi"),
        Verb = "runas"
    }
};
p.Start();
p.WaitForExit();
int exitCode = p.ExitCode;

If the setup.msi has not been previously installed it is installing to silent mode and returns 0. It normal.

But if setup.msi already installed (launch this code second time), installation not starting and return code 0 - success result! But in fact, the files have not been established, because product is already installed. How I can determine this situation?

riQQ
  • 4,188
  • 4
  • 19
  • 33
Nikolay
  • 577
  • 6
  • 20
  • If the product is already installed you should get **1638** as error code, Have you tried to install this MSI manually and see if you are getting the *product already exist* message ? – Kurubaran Sep 09 '14 at 08:07
  • When I start the installation manually, I see that the product is installed. There are two options: Repair and Remove. But if I launch with parameters in silent mode msiexec return success code (0). – Nikolay Sep 09 '14 at 08:37
  • try /passive switch on msiexec – ths Sep 09 '14 at 22:03
  • Added an answer on how to use the MSI COM API to check installation state in 2 lines. – Stein Åsmul Jan 10 '20 at 02:16

3 Answers3

4

You received an exit code of 0 because the product is already installed and you are not attempting to install a new version. In otherwords, your MSI does not have a new Product Code and version number, therefore the MSIExec installer considers it a reconfiguration, and exits. I tested this out by turning on the /log switch and reading the output after installing one of my MSI files twice.

MSI (c) (98:EC) [15:19:27:912]: Product: Product Name -- Configuration completed successfully. MSI (c) (98:EC) [15:19:27:912]: Windows Installer reconfigured the product. Product Name: Product Name. Product Version: 4.8.22. Product Language: 1033. Manufacturer: Manufacturer. Reconfiguration success or error status: 0.

If you were trying to install a new version of your product and your MSI was not configured to remove previous versions, you would receive an error code of 1638. See list of error codes here: MSDN

If you want to check if the product is already installed with the existing MSI information (not an upgrade) you would need to check the registry at: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\YourProductCode

If it turns out it is installed (according to the system/registry -- maybe the files were deleted but it still is considered to be installed) you can try uninstalling it using the /x or /uninstall switch and then reinstalling. You could also use the /fa switch to do a repair and reinstall all files.

msiexec.exe /x ProductCode will uninstall it. Then you can run the install again after that. msiexec.exe /fa ProductCode will do a repair of all files. The /f switch has a lot of different options for how it reinstalls files, so you'd do well to read the link to the msiexec switches article I posted above.

Some other notes about msiexec:

/qb displays a basic user interface. You probably want /qn. When I was setting up my live-update software I ran into a bunch of problems, I had to make sure I called msiexec from system32 by using

p.StartInfo.FileName == Path.Combine(System.Environment.ExpandEnvironmentVariables("%windir%\\system32"), "MSIExec.exe"); 
pinkfloydx33
  • 9,666
  • 3
  • 34
  • 51
3

First, the other remarks concerning 1638 return code are a bit misleading. When you install the exact MSI file a second time, you get a return code 0 like you already (and correctly) observed. That's "correct" behaviour or in other words: That's how MSI is designed. Moreover there are no changes made to your existing setup in this case. If you delete all files before the second install, you end up with nothing although MSI is returning zero. So return code alone is not helping you for this scenario.

In short terms, you have the following possibilities:

  1. Easy but seems unnormal: Just uninstall (maybe silently) the product before you install with:

    msiexec /x {yourproductcode} /qn

(You will not get an error even if the product has been NOT installed before because of the silent parameter "/qn"

  1. Advised if enough for you: Just use the repair mode if you want to install a second time: Example:

    msiexec /i ... REINSTALL=ALL REINSTALLMODE=vemus

  2. Optimal: Use a launcher (boot-strapper or other names are the same thing) to test IF the product is already installed, etc. With this you can automate the previous options (pre-uninstall or add of repair parameters). This can be done also with scripts but in each case this is programming, so not the easiest way.

4.

Now we come to the mentioned 1638 return code in some other answers: IF (and only if) your build system (like InstallShield does by default) changes the socalled MSI PackageCode) in every build AND you are trying to update this slightly different built (MSI) to a previous installed one, you get the 1638 return code.

These things are often misunderstood. Changing the PackageCode for every build is a very recommended practice. On the other hand it will complicate things for you not only a bit, if you will release such MSIs to your customers. The name of this update type is "small update or minor upgrade" (their difference is not important here, because it has the same limitations for you. If you really want to solve your problem with a return code, you can use this. But as said, the 1638 you will not get for the second install of the exactly SAME MSI !

To continue the recommendation about updates, there are more ways: the easiest to handle way (for beginners) are Major Upgrades. This is what is called "new version" in another answer which was not wrong, but not so exact. For Major Upgrades you have to change MSI PackageCode and MSI ProductCode at minimum, recommended is changing the ProductVersion also. (Another way would be to use MSI patches as delta updates, but this is not easy either).

Philm
  • 2,953
  • 24
  • 23
1

MSI COM API: If you can use the MSI COM API you can use the ProductState property. In other words you can check for an installed product with two lines of code if you have the actual product code (How can I find the product GUID of an installed MSI setup?):

Dim installer : Set installer = CreateObject("WindowsInstaller.Installer")
MsgBox installer.ProductState("{00000000-0000-0000-0000-000000000001}") ' <= PRODUCT CODE

Results: The normal states are 5 for installed or -1 for not installed:

INSTALLSTATE_UNKNOWN   -1  The product is neither advertised or installed.
INSTALLSTATE_ADVERTISED 1  The product is advertised but not installed.
INSTALLSTATE_ABSENT     2  The product is installed for a different user.
INSTALLSTATE_DEFAULT    5  The product is installed for the current user.

Interactive VBScript: Here is a larger version of the VBScript with interactive input of product GUID in an InputBox - for use with any product GUID in an ad-hoc fashion: CheckProductState-Interactive.vbs


Links:

Stein Åsmul
  • 34,628
  • 23
  • 78
  • 140