windows 如何测试另一个安装是否已经在进行中?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/140820/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 11:19:27  来源:igfitidea点击:

How do I test if another installation is already in progress?

c#windowswindows-installer

提问by Wedge

Assuming I'm trying to automate the installation of something on windows and I want to try to test whether another installation is in progress before attempting install. I don't have control over the installer and have to do this in the automation framework. Is there a better way to do this, some win32 api?, than just testing if msiexec is running?

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

[Update 2]

[更新2]

Improved the previous code I had been using to just access the mutex directly, this is a lot 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;
}

采纳答案by Mike Dimmick

See the description of the _MSIExecute Mutexon MSDN.

请参阅MSDN 上_MSIExecute Mutex的说明。

回答by NBPC77

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

我使用上面的代码得到了一个未处理的异常。我相互参照这篇文章威特这一个

Here's 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;

}

回答by Roadie

Sorry for hiHymaning you post!

很抱歉劫持您的帖子!

I have been working on this - for about a week - using your notes (Thank you) and that from other sites - too many to name (Thank you all).

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

I stumbled across information revealing that the Service could yield enough information to determine if the MSIEXEC service is already in use. The Service being 'msiserver' - Windows Installer - and it's information being both state and acceptstop.

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

The following VBScript code checks this.

下面的 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