8

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

[更新 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;
}
4

3 回答 3

6

请参阅MSDN 上_MSIExecute Mutex的描述。

于 2008-09-26T17:40:43.270 回答
3

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

这是我更新的代码:

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

}
于 2014-02-25T21:20:01.813 回答
2

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

我偶然发现了一些信息,表明该服务可以产生足够的信息来确定 MSIEXEC 服务是否已经在使用中。服务是“msiserver”——Windows 安装程序——它的信息既是 state 又是 acceptstop。

以下 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
于 2015-11-11T14:22:49.483 回答