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
- Carolyn, MSI Team Dev Lead. You can get other Carolyn insights about developing for Windows Installer from the Windows Installer Chat Archives
- Hem, MSI Team Dev. You can get other Hem insights about developing for Windows Installer from the Windows Installer Chat Archives
[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.