【问题标题】:How do I test if another installation is already in progress?我如何测试另一个安装是否已经在进行中?
【发布时间】:2008-09-26 17:30:50
【问题描述】:

假设我正在尝试在 Windows 上自动安装某些东西,并且我想在尝试安装之前尝试测试是否正在进行另一个安装。我无法控制安装程序,必须在自动化框架中执行此操作。有没有比仅仅测试 msiexec 是否正在运行更好的方法,一些 win32 api?

[更新 2]

改进了我之前使用的直接访问互斥锁的代码,这更加可靠:

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

【问题讨论】:

  • 当您打开没有 MutexRights.Modify 标志的现有互斥锁时,您无法释放互斥锁,因为您无法拥有它。来自msdn:MutexRights.Synchronize 允许线程在互斥体上等待,MutexRights.Modify 允许线程调用ReleaseMutex 方法。 msdn.microsoft.com/en-us/library/c41ybyt3.aspx

标签: c# windows windows-installer


【解决方案1】:

参见 MSDN 上_MSIExecute Mutex 的描述。

【讨论】:

    【解决方案2】:

    使用上面的代码,我得到了一个未处理的异常。我交叉引用了这篇文章,one

    这是我更新的代码:

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

    【讨论】:

    • 你为什么将 MSIExecuteMutex.WaitOne() 中的 exitContext 指定为 false
    【解决方案3】:

    我一直在研究这个 - 大约一个星期 - 使用你的笔记(谢谢)和其他网站的笔记 - 太多了(谢谢大家)。

    我偶然发现了一些信息,表明该服务可以产生足够的信息来确定 MSIEXEC 服务是否已在使用中。服务是 'msiserver' - Windows Installer - 它的信息是状态和接受停止。

    以下 VBScript 代码对此进行检查:

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-04
      • 2011-08-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-25
      • 1970-01-01
      相关资源
      最近更新 更多