Windows Installer Troubleshooting Tips From Halloween

Question 1

In my lab automation that silently installs Windows Installer packages. This automation is inconsistently getting Error 1618 from its msiexec calls. Please help unblock this scenario as it's inhibiting our push to ship.

Troubleshooting 1

First, start with the MSDN Library and run a search for "windows installer" 1618. This query (when I click it) turns up Initialization Errors [Windows Installer] as the sixth hit. This page contains

Error code Value Error
ERROR_INSTALL_ALREADY_RUNNING 1618 An installation is already in progress

Next, have a look at the machine event log and look for the messages per the MSDN Topic Event Logging

Finally, when one puts this information together, the chances are high that another process, such as SMS or Group Policy, is triggering a silent install of a MSI based product thus the mutex is preventing the simultaneous install of the second product.

Solutions 1

To solve for this scenario, one needs to understand the mechanics of determining if Windows Installer is busy and then one needs to consider the appropriate behavior for their application for the "busy" case. 

Generally if Windows Installer is busy , Windows Installer will set the Mutex.  For a sample demonstrating the mechanics of checking the mutex, see the Windows Installer Platform SDK bootstrapper code example

HANDLE hMutex = 0;
bool bInstallRunning = false;

const char *szMutexName = "Global\\_MSISETUP_{2956EBA1-9B5A-4679-8618-357136DA66CA}";
hMutex = WIN::CreateMutex(NULL /*default security descriptor*/, FALSE, szMutexName);
if (!hMutex || ERROR_ALREADY_EXISTS == GetLastError())
{
bInstallRunning = true;
}
else
{
bInstallRunning = false;
}

// only run one instance at a time
if (bInstallRunning)
{
// silently return - correct return code ?
uiRet = ERROR_INSTALL_ALREADY_RUNNING;
goto CleanUp;
}

// do work here

CleanUp:
if(hMutex)
CloseHandle(hMutex);

For Windows Installer 3.0 or greater, we recommend switching from the mutex to attempting to stop the msi service.  If you are unable to stop the service, the service is busy installing another product.  In pseudocode, these mechanics would look like

 if (MSIServer is not running)
    bInstallRunning = true; // because if the service isn't running there can't be an install running
else  if (MSIServer accepts SERVICE_ACCEPT_STOP)
    bInstallRunning = false; // because if it can stop it can't be installing something
else
    bInstallRunning = false; // because it won't accept the stop, so it's doing an install. 

With either of these solutions, a non-privileged context will be unable to detect the state of the engine.

Now that you know the mechanics, you need to consider what to do when the Windows Installer is "busy".  There are a number of options and which one you choose depends on your judgment.  Some solutions choose surface the fact that the Windows Installer is busy and suggest the user try again later.  Other solutions choose to put the "busy" check in a polling loop and attempt an auto recover from the mutex. 

Question 2

I have a Windows Installer package that InstallInitialize shows all the features and components are installing Action:Local but after the install the feature is advertised. Can you help explain this? (msi packages and verbose logs sent too)

Answer 2

Generally to find these issues I look at the components with conditions. In this case we have the following Component Table Fragments

Component ComponentId Directory_ Attributes Condition KeyPath
C_Server_ConnectorKeys_For_NonRMS.540EA3C0_A5E9_41EA_A585_822C09EA2650 {3162C002-E983-4C45-BE65-A0EADF35AD49} SDK_DIR.540EA3C0_A5E9_41EA_A585_822C09EA2650 4 IS_ROOT_HEALTH_SERVICE=0 R_Server_ConnectorKeys_For_NonRMS10.540EA3C0_A5E9_41EA_A585_822C09EA2650
C_Core_ConnectorKeys.80B659D9_F758_4E7D_B4FA_E53FC737DCC9 {43DC7EF4-E685-45E1-9B3B-9843A2853E43} CORE_DIR.80B659D9_F758_4E7D_B4FA_E53FC737DCC9 4 USE_SETTINGS_FROM_AD=0 R_Core_Connector01.80B659D9_F758_4E7D_B4FA_E53FC737DCC9

Cross Referencing the C_Server_ConnectorKeys_For_NonRMS.540EA3C0_A5E9_41EA_A585_822C09EA2650 GUID {3162C002-E983-4C45-BE65-A0EADF35AD49} with the install log and one finds

MSI (s) (44:6C) [14:26:41:656]: Executing op: ComponentUnregister(ComponentId={3162C002-E983-4C45-BE65-A0EADF35AD49},,BinaryType=0,PreviouslyPinned=1)

Now I take the condition and search for it in the log

 MSI (s) (44!AC) [14:26:26:828]: PROPERTY CHANGE: Modifying IS_ROOT_HEALTH_SERVICE property. Its current value is '0'. Its new value: '1'.
 ...
 Property(S): IS_ROOT_HEALTH_SERVICE = 1

If it were true that this property was set, it would cause the component to be absent and its absence would cause the feature to appear advertised.

Design Suggestion for Question 2

If the advertised state on the feature is the problem, I suspect what’s called for here is another feature. One could have a child feature that just contains the components that will be toggled and is marked to follow parent. Depending on whether that works for all scenarios, there is also the option to have the new feature sit at the root and then write code to toggle the state of the feature.

Editing credit also belongs to

  • Phil Wilson, MSI MVP,

Content credit also belongs to

[Author: Robert Flaming]

This posting is provided "AS IS" with no warranties, and confers no rights. Use of included script samples are subject to the terms specified at https://www.microsoft.com/info/cpyright.htm.