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