How to check if another installation is in progress?

Assuming I'm trying to automate the installation of something on Windows, and I want to try to check if another installation is running before trying to install. I have no control over the installer, and I have to do this as part of the automation. Is there a better way to do this, some kind of Win32 API? Than just check if msiexec is working?

[Update 2]

The previous code that I used for direct access to the mutex is improved, it is much more reliable:

using System.Threading; [...] /// <summary> /// Wait (up to a timeout) for the MSI installer service to become free. /// </summary> /// <returns> /// Returns true for a successful wait, when the installer service has become free. /// Returns false when waiting for the installer service has exceeded the timeout. /// </returns> public static bool WaitForInstallerServiceToBeFree(TimeSpan maxWaitTime) { // The _MSIExecute mutex is used by the MSI installer service to serialize installations // and prevent multiple MSI based installations happening at the same time. // For more info: http://msdn.microsoft.com/en-us/library/aa372909(VS.85).aspx const string installerServiceMutexName = "Global\\_MSIExecute"; try { Mutex MSIExecuteMutex = Mutex.OpenExisting(installerServiceMutexName, System.Security.AccessControl.MutexRights.Synchronize | System.Security.AccessControl.MutexRights.Modify); bool waitSuccess = MSIExecuteMutex.WaitOne(maxWaitTime, false); MSIExecuteMutex.ReleaseMutex(); return waitSuccess; } catch (WaitHandleCannotBeOpenedException) { // Mutex doesn't exist, do nothing } catch (ObjectDisposedException) { // Mutex was disposed between opening it and attempting to wait on it, do nothing } return true; } 
+8
c # windows windows-installer
source share
3 answers

See _ MSIExecute Mutex on MSDN.

+6
source share

I was getting an unhandled exception using the code above. I cross-reference this article witt this one

Here is my updated code:

  /// <summary> /// Wait (up to a timeout) for the MSI installer service to become free. /// </summary> /// <returns> /// Returns true for a successful wait, when the installer service has become free. /// Returns false when waiting for the installer service has exceeded the timeout. /// </returns> public static bool IsMsiExecFree(TimeSpan maxWaitTime) { // The _MSIExecute mutex is used by the MSI installer service to serialize installations // and prevent multiple MSI based installations happening at the same time. // For more info: http://msdn.microsoft.com/en-us/library/aa372909(VS.85).aspx const string installerServiceMutexName = "Global\\_MSIExecute"; Mutex MSIExecuteMutex = null; var isMsiExecFree = false; try { MSIExecuteMutex = Mutex.OpenExisting(installerServiceMutexName, System.Security.AccessControl.MutexRights.Synchronize); isMsiExecFree = MSIExecuteMutex.WaitOne(maxWaitTime, false); } catch (WaitHandleCannotBeOpenedException) { // Mutex doesn't exist, do nothing isMsiExecFree = true; } catch (ObjectDisposedException) { // Mutex was disposed between opening it and attempting to wait on it, do nothing isMsiExecFree = true; } finally { if(MSIExecuteMutex != null && isMsiExecFree) MSIExecuteMutex.ReleaseMutex(); } return isMsiExecFree; } 
+3
source share

I apologize for the hijacking!

I have been working on this - for about a week - using your notes (thanks), and from other sites - too much to name (thanks to everyone).

I came across information showing that the Service can provide enough information to determine if the MSIEXEC service is already in use. The "msiserver" service is a Windows installer - and this information is both state and acceptstop.

The following VBScript code verifies this.

 Set objWMIService = GetObject("winmgmts:\\.\root\cimv2") Check = False Do While Not Check WScript.Sleep 3000 Set colServices = objWMIService.ExecQuery("Select * From Win32_Service Where Name="'msiserver'") For Each objService In colServices If (objService.Started And Not objService.AcceptStop) WScript.Echo "Another .MSI is running." ElseIf ((objService.Started And objService.AcceptStop) Or Not objService.Started) Then WScript.Echo "Ready to install an .MSI application." Check = True End If Next Loop 
+2
source share

All Articles