通过Process.Start排队安装

时间:2013-01-24 14:53:13

标签: c# windows process windows-installer system.diagnostics

我需要对大约20个完全无人值守的安装进行排队(使用C#winform应用程序)。每个安装都有自己的INI文件(手动创建),该文件包含每个安装程序对此过程所需的参数的正确信息(在执行该程序之前读入)。我遇到许多应用程序的问题,当执行setup.exe时,进程立即关闭并启动其MSI(如果适用),导致我的程序执行下一个安装,假设第一个完成。我已经阅读了类似的问题窥探网络,但在这个问题上没有真正的解决方案......(一些解决方法包括使用带有/ Wait选项的批处理文件,它应该将setup.exe保留在内存中直到其MSI完成)。必须启动setup.exe,因为它们包含bootstrappers。

我有什么选择来解决这个难题?

以下是一些演示过程的示例代码:

            foreach (ListViewItem itm in this.lstSoftwares.Items)
            {
                try
                {
                    if (itm.Checked)
                    {
                        lblStatus.Text = "Status: Installing " + current.ToString() + " of " + count.ToString();

                        string InstallPath = Path.Combine(Application.StartupPath, "Software",
                        itm.Text, itm.Tag.ToString());

                        string CommandLine = itm.SubItems[1].Text;

                        Process process = new Process();
                        process.StartInfo.FileName = InstallPath;
                        process.StartInfo.Arguments = CommandLine;

                        process.StartInfo.WindowStyle = ProcessWindowStyle.Normal;
                        process.Start();
                        process.WaitForExit();
                        this.lstSoftwares.Items[i].SubItems[2].Text = "Complete";
                        current++;
                    }

更新

在waitforexit()之后

我正在使用一个循环来检查msiexec是否正在运行:

    private bool MSIRunning()
    {           
        try
        {
            using (var mutex = Mutex.OpenExisting(@"Global\_MSIExecute"))
            {                   
                return true;
            }

        }
        catch (Exception)
        {
            return false;
        }
    }

这是我的选择中的一个黑客攻击,但到目前为止这个伎俩...

2 个答案:

答案 0 :(得分:0)

在循环中的process.start之后查询MSI Mutex(检查Mutex是否每3秒运行一次,如果没有返回并继续下一次安装)似乎解决了这个问题(上面注明)。

答案 1 :(得分:0)

已经回答了,但我对MSI互斥检查的执行稍微强一些:

public bool IsMsiExecFree(TimeSpan maxWaitTime)
{
    _logger.Info(@"Waiting up to {0}s for Global\_MSIExecute mutex to become free...", maxWaitTime.TotalSeconds);

    // 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,
            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();
    }

    _logger.Info(@"Global\_MSIExecute mutex is free, or {0}s has elapsed.", maxWaitTime.TotalSeconds);

    return isMsiExecFree;
}