0

我有自己的 Updater.exe,它启动 InstallShield Suite 安装程序(嵌入了另外两个 InstallShield MSI)。我想从 Suite Installer 获取安装进度状态消息并显示在我的 Updater.exe UI 中。

是否可以轮询/ping 安装程序以获取安装状态消息?(如登台、安装 msi1、安装 msi2、配置、安装完成)。

我在我的安装程序中使用 .NET Framework 4.5+ 作为先决条件,Installshield 版本 2016,用于自定义操作的 wiX 工具集。

4

1 回答 1

0

InstallShield 2016 没有任何开箱即用的功能来在安装过程中获取状态消息。

我最终编写了自己的工具来监视使用调试日志参数生成的调试日志中的 installshield 属性值。

InstallShield 安装程序调试日志:

语法:Installer.exe /debuglog"logfilepath"

例如:installer.exe /debuglog"c:\users\test.user\desktop\debuglog.log"

InstallShield 设置了三种不同的状态类型,即;'ISProgressSummary'、'ISInstallStatus' 和 'ISParcelStatus' 并记录到调试日志中。

示例 installshield 调试日志条目是:

2019 年 9 月 23 日 [上午 10 点 40 分 56 秒]:引擎:属性“ISProgressSummary”值现在“正在安装您选择的程序功能。”

2019 年 9 月 23 日 [上午 10 点 41 分 12 秒]:引擎:属性“ISInstallStatus”值现在“正在安装包 Microsoft Visual C++ 2012 Update 4 Redistributable Package (x86)”

2019 年 9 月 23 日[上午 10 点 41 分 17 秒]:引擎:属性“ISParcelStatus”值现在“计算空间要求”

下面的 C# 代码监视调试日志并调用事件处理程序。您创建一个以下类的对象并发送您要监视的“statusType”。statusType 可以是 ISProgressSummary、ISInstallStatus、ISParcelStatus

public class LogFileMonitorLineEventArgs : EventArgs
{
    public string Line { get; set; }
}

public class LogFileMonitor
{
    public EventHandler<LogFileMonitorLineEventArgs> OnLine;

    readonly string _path;
    readonly string _delimiter;
    readonly string _statusType;

    Timer _timer;

    long _currentSize;
    bool _isCheckingLog;

    protected bool StartCheckingLog()
    {
        lock (_timer)
        {
            if (_isCheckingLog)
                return true;

            _isCheckingLog = true;
            return false;
        }
    }

    protected void DoneCheckingLog()
    {
        lock (_timer)
            _isCheckingLog = false;
    }

    public LogFileMonitor(string path, string delimiter = "\n", string statusType = "")
    {
        _path = path;
        _delimiter = delimiter;
        _statusType = statusType;
    }

    public void Start()
    {
        _currentSize = new FileInfo(_path).Length;

        _timer = new Timer(1000);
        _timer.Elapsed += CheckLog;
        _timer.AutoReset = true;
        _timer.Start();
    }

    private void CheckLog(object s, ElapsedEventArgs e)
    {
        if (!StartCheckingLog()) return;

        try
        {
            var newSize = new FileInfo(_path).Length;

            if (_currentSize == newSize)
                return;

            using (FileStream stream = File.Open(_path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
            using (StreamReader sr = new StreamReader(stream, Encoding.Unicode))
            {
                sr.BaseStream.Seek(_currentSize, SeekOrigin.Begin);

                var newData = sr.ReadToEnd();
                if (!newData.EndsWith(_delimiter))
                {
                    if (newData.IndexOf(_delimiter, StringComparison.Ordinal) == -1)
                    {
                        newData = string.Empty;
                    }
                    else
                    {
                        var pos = newData.LastIndexOf(_delimiter, StringComparison.Ordinal) + _delimiter.Length;
                        newData = newData.Substring(0, pos);
                    }
                }

                string[] lines = newData.Split(new[] { _delimiter }, StringSplitOptions.RemoveEmptyEntries);

                string lastInstallStatus = string.Empty;

                foreach (string line in lines)
                {
                    if (line.Contains(_statusType))
                    {
                        lastInstallStatus = line;
                        OnLine?.Invoke(this, new LogFileMonitorLineEventArgs { Line = lastInstallStatus });
                    }
                }
            }

            _currentSize = newSize;
        }
        catch (Exception)
        {
        }

        DoneCheckingLog();
    }

    public void Stop()
    {
        _timer?.Stop();
    }
}
于 2019-09-27T21:33:44.130 回答