I am creating a WIX installer bootstrapper (with DisplayInternalUI="yes"
on the msipackage), but it hangs when there are other installations occurring at the same time.
If i run the MSI file on its own using msiexec I get a windows installer error
"Another installation is in progress"
message (i.e 1500 MSI error message) - and I presume this is hanging my install.
Therefore what I am doing is seeing if I can lock the _MSIExecute mutex
just after the user presses the Install button (i.e. before the ProgressDlg
). If I can lock the Mutex then there are no other installs in progress - therefore it is safe to proceed with the install (i.e. the execution phase) . If not the installer shows a cancel button (and no other buttons) - so the install will not proceed.
I was wondering if there was a way of preventing the "Another installation is in progress"
error message (and other messages) from hanging the installer.
No MSI Concurrency: Why are there other installations happening "at the same time" - or in other words concurrently? I am not too potty-trained when it comes to WiX Burn bootstrappers, but I am wondering if the MSI in question contains any custom actions which kicks off other MSI installs? This is not allowed for MSI packages. You can not have two concurrent InstallExecuteSequences
running at the same time. Hence you can not kick off an MSI from within an InstallExecuteSequence
. Some people try to kick off installs from the InstallUISequence
, which is also very unadvisable for many reasons - for one thing it won't run at all when the setup is run in silent mode. I also suspect potential issues with elevation, and unexpected setup failure if you set check exit code for the custom action, and that kind of stuff. It always permutes. The basic rule of thumb to remember is: Custom actions must never launch other MSI installations. The WiX Burn bootstrapper basically specifically exists to allow you to run MSI files in sequence - and not concurrently - but it is also more: it is a combined bootstrapper, chainer, downloader, etc...
Mutex: Strong words, but if you know what is good for you, you will stay away from MSI mutexes. Save yourself! :-). MSI is a technology which fights back, and you will be fighting windmills for real if you take the fight. That is all I can say to warn you. It really is impossible to deal with unless you follow the basic rules, which in this case is one installer running at a time. The WiX guys could deal with it though - leave it to them - and use their tool propery (WiX Burn). Though the technical details are unclear to me, they will certainly have features implemented to do exactly what you describe (check if the system is ready for installation).
Suspended Installation: It is also possible that there is a suspended installation on your system that needs to be undone before you can install MSI files at all. Can you try to install another MSI file and see if it runs correctly? I am not 100% sure this is the right link, but you can also try: Fix problems that block programs from being installed or removed.
UPDATE: With regards to _MSIExecute Mutex. See towards bottom for technical info on checking the current Windows Installer status using QueryServiceStatusEx. Heath Stewart suggests another way (sample C++ code).
Also, some pre-existing, related answers:
- check for windows installer mutex availability
- How to detect a running MSI Installation
- Windows Installer always says “Another program is being installed”
First some comments on the issue at hand (virtuals updating and pending reboots):
Windows Updates In Progress: If you are dealing with the situation where Windows Updates are being performed in the background and MSI installations won't run, then it is possible that WiX Burn might hang whilst checking whether a system reboot is pending. I have seen issues like this before (see "technical issues" below).
Real Fix: If this is the case the only real fix is to let the Windows Updates finish and then reboot and persist a new virtual machine state and then install your package. This is the only sane fix - in my opinion. Not what you want to hear :-).
Dirty "Fix": I suppose you could also stop the Windows Update service to prevent Windows Updates from installing, but my guess is that your virtual will be infected with malware eventually if you do this, and then you have the horrible situation that you may accidentally persist malware in your virtual that is then resurrected regularly and not detected by security software (which often does not scan virtuals). This might be one of the worst malware vectors in existence due to the difficulty of erradicating it and discovering it (in the same league as malware on read-only media and malware checked into source control systems - there might not be an easy way to get rid of it). Well-meant advice (the kind that is never wanted - we all live in reality): please do not disable Windows Update on your virtual without a proper consideration of consequences. Corporate-wide I would never allow such a thing - only as exceptions for specific users who have testing needs beyond normal - and the virtuals would be forcibly malware checked regularly. Which reminds me to check what security software can scan offline virtuals properly. More research to do. Funny that, writing stackoverflow answers always teaches me what I don't do properly myself! Not good :-).
Technical Issues: As to the technicalities. I have seen issues before where WiX Burn hangs because it specifically tries to avoid installing on a system that is being updated:
- WiX behaving badly on XP machine with windows update issues
- How do I reference the Reboot Pending Property in Burn (WiX) (recommended)
Maybe check if that little VBScript in the linked answers (or equivalent COM call in whatever language you want) will tell you if the system is not ready for installation?
The Simple Hack?: Not verified, but maybe you can check the registry key / value (not sure whether this is a value or a key): HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer : InProgress
- it should be present to indicate an active Windows Installer session - as far as I know. I think this is better than trying to handle mutexes and other OS fundamentals.
Strangely I am not aware of any MSI API calls that will tell you whether there is an active installation session (mutex set). The only thing I can see is a Win32 function (i.e not COM automation): MsiBeginTransaction (a very recent addition to the MSI API, 4.5 up only).
There is also this: MSDN: _MSIExecute Mutex - suggesting to use QueryServiceStatusEx and check whether the value of dwControlsAccepted
is SERVICE_ACCEPT_SHUTDOWN
. I have never tried it. Frankly I would try to check the above registry key instead.
If Windows Update is your main concern, then you'd use the Windows Update Agent API to detect if there is an update in progress. I think you'd need to run it from your own bootstrapper before attempting to install the MSI. The general C++ idea is as follows:
#include "stdafx.h"
#include <wuapi.h>
#include <iostream>
#include <ATLComTime.h>
#include <wuerror.h>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
HRESULT hr;
hr = CoInitialize(NULL);
IUpdateSession* iUpdate;
IUpdateSearcher* searcher;
IUpdateInstaller* iInstaller;
ISearchResult* results;
BSTR criteria = SysAllocString(L"IsInstalled=1 or IsHidden=1 or
IsPresent=1");
hr = CoCreateInstance(CLSID_UpdateInstaller, NULL,
CLSCTX_INPROC_SERVER, IID_IUpdateInstaller, (LPVOID*)&iInstaller);
VARIANT_BOOL Busy;
hr = iInstaller->get_IsBusy(&Busy);
etc
Basically the IsBusy property tells you if an update is in process.
https://msdn.microsoft.com/en-us/library/windows/desktop/aa386502(v=vs.85).aspx
The discussion thread here:
http://windows-installer-xml-wix-toolset.687559.n2.nabble.com/Windows-Updates-either-pending-or-running-causes-our-installs-to-fail-td7598536.html
also has a better code example. I'm not aware of a managed code interface or built-in WiX support.