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 http://www.microsoft.com/info/cpyright.htm.

Comments (7)

  1. Why not simply create a "MsiisBusy()" API and support it?

    I and others also get 1618 a lot when we know that Windows Installer is not busy (and the remote box will keep returneing 1618 over a very long extended peoriod of time) and can prove this by logging onto the remote box and manually doing it.

    Is it possible there is a MSI related WMI BUG which is perhaps causing the local machine to be check for busy and not the remote one?

  2. Ajay Ladsaria says:

    Are there any negative ramifications of the feature appearing as advertised in subsequent operations such as upgrades and uninstalls?

    -Ajay

  3. zhakim says:

    Phil Wilson, MSI MVP has pointed out the eariler code post had two bugs. I’ve corrected the pseudo code above. Below are the bugs found. Many thanks to Phil! ;^)

    if (!hMutex || ERROR_ALREADY_EXISTS == GetLastError())

    {

    bInstallRunning = true;

    }

    bInstallRunning = false;

    is now

    if (!hMutex || ERROR_ALREADY_EXISTS == GetLastError())

    {

    bInstallRunning = true;

    }

    else

    {

    bInstallRunning = false;

    }

    and

    if (MSIServer is not running)

    bInstallRunning = true;

    else if (MSIServer accepts SERVICE_ACCEPT_STOP)

    bInstallRunning = true;

    else

    bInstallRunning = false;

    is now

    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.

  4. mikeb says:

    Shouldn’t:

    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.

    really be:

    if (MSIServer is not running)

    bInstallRunning = false; // 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 = true; // because it won’t accept the stop, so it’s doing an install.

  5. Phil Wilson says:

    1) I agree with mikeb that that final line should set bInstallRunning to true.

    2) The "checking the service" approach may have some timing issues. It seems to me that any number of threads could go through that algorithm and all conclude that they can start up their MSI, but most will fail. The mutex approach works like a gate that lets one person through at a time, but checking that the Service isn’t busy with an install doesn’t have that one-at-a-time property.

  6. Checking the service state or acceptance of the stop request isn’t thread-safe. Unless support for the _MSIExecute mutex is going away – and I doubt that since the Windows Installer team is very good about backward compatibility – I would rather use thread-safe code as with the sample at http://blogs.msdn.com/heaths/archive/2006/01/23/516454.aspx.

  7. Some have noticed that the msiexec.exe process seems to run for quite some time after a known installation

Skip to main content