2008-09-26 25 views
7

Suponiendo que estoy tratando de automatizar la instalación de algo en Windows y quiero intentar probar si hay otra instalación en progreso antes de intentar la instalación. No tengo control sobre el instalador y tengo que hacer esto en el marco de automatización. ¿Hay una mejor manera de hacer esto, alguna API de win32 ?, que simplemente probar si se está ejecutando msiexec?¿Cómo compruebo si ya hay otra instalación en curso?

[Actualización 2]

Mejora el código anterior que había estado utilizando sólo acceder al mutex directamente, esto es mucho más fiable:

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); 
     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; 
} 
+2

Cuando abre un mutex existente sin el indicador MutexRights.Modify no puede liberar el mutex porque no puede ser el propietario. Desde msdn: MutexRights.Synchronize permite que un subproceso espere en el mutex, y MutexRights.Modify permite que un subproceso llame al método ReleaseMutex. http://msdn.microsoft.com/en-us/library/c41ybyt3.aspx –

Respuesta

2

Recibí una excepción no controlada utilizando el código anterior. Me referencias cruzadas este artículo Witt este one

Aquí está mi código actualizado:

/// <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; 

} 
2

Lo siento por el secuestro de publicar!

He estado trabajando en esto - durante aproximadamente una semana - utilizando sus notas (Gracias) y las de otros sitios - Demasiadas para nombrar (Gracias a todos).

Me tropecé con información que revela que el Servicio podría proporcionar suficiente información para determinar si el servicio MSIEXEC ya está en uso. El Servicio es 'msiserver' - Windows Installer - y su información es tanto state como accepttop.

El siguiente código de VBScript comprueba esto.

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 
Cuestiones relacionadas