通过 Process.Start 对安装进行排队
本文关键字:排队 安装 Process Start 通过 | 更新日期: 2023-09-27 17:55:54
我需要对大约 20 个完全无人参与的安装进行排队(使用 C# winform 应用程序)。每个安装都有自己的 INI 文件(手动创建),其中包含有关每个安装程序需要此过程的参数的正确信息(在执行该程序之前读入)。 我遇到了许多应用程序的问题,当执行安装程序.exe时,该过程会立即关闭并启动其 MSI(如果适用),导致我的程序在下一次安装中执行,假设第一个安装已完成。我读过类似的问题,在网上窥探,但没有关于这个问题的真正解决方案......(一些解决方法包括使用带有/Wait 选项的批处理文件,该文件应将安装程序.exe保留在内存中,直到其 MSI 完成)。安装程序.exe必须启动,因为它们包含引导程序。
我有什么选择来解决这个困境?
下面是一些演示该过程的示例代码:
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++;
}
更新
在等待退出()之后,我正在使用一个循环来检查 msiecc 是否正在运行:
private bool MSIRunning()
{
try
{
using (var mutex = Mutex.OpenExisting(@"Global'_MSIExecute"))
{
return true;
}
}
catch (Exception)
{
return false;
}
}
这是我的观点中的一个黑客,但到目前为止一直在做这个技巧......
在循环中查询 process.start 后查询 MSI 互斥体(检查互斥体是否每 3 秒运行一次,如果没有返回并继续下一次安装)似乎解决了这个问题(如上所述)。
已经回答了,但我有一个稍微健壮的 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;
}