From 47582b162368e8edf7a3b11c13b8e9dabc5f0a26 Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Thu, 31 Mar 2022 11:56:14 -0700 Subject: Provide managed CA and Embedded UI DTF libraries via NuGet Lots of refactoring to bring the SFX tooling back into the 'dtf' layer since they are (in the end) tightly coupled to some DTF assemblies. Also refactored the DTF tests into their own folder and added a couple integration tests to build using the new CA/UI NuGet package. Closes wixtoolset/issues#6080 --- src/test/dtf/EmbeddedUI/InstallProgressCounter.cs | 174 ++++++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 src/test/dtf/EmbeddedUI/InstallProgressCounter.cs (limited to 'src/test/dtf/EmbeddedUI/InstallProgressCounter.cs') diff --git a/src/test/dtf/EmbeddedUI/InstallProgressCounter.cs b/src/test/dtf/EmbeddedUI/InstallProgressCounter.cs new file mode 100644 index 00000000..3d75081c --- /dev/null +++ b/src/test/dtf/EmbeddedUI/InstallProgressCounter.cs @@ -0,0 +1,174 @@ +namespace WixToolset.Samples.EmbeddedUI +{ + using System; + using WixToolset.Dtf.WindowsInstaller; + + /// + /// Tracks MSI progress messages and converts them to usable progress. + /// + public class InstallProgressCounter + { + private int total; + private int completed; + private int step; + private bool moveForward; + private bool enableActionData; + private int progressPhase; + private double scriptPhaseWeight; + + public InstallProgressCounter() : this(0.3) + { + } + + public InstallProgressCounter(double scriptPhaseWeight) + { + if (!(0 <= scriptPhaseWeight && scriptPhaseWeight <= 1)) + { + throw new ArgumentOutOfRangeException("scriptPhaseWeight"); + } + + this.scriptPhaseWeight = scriptPhaseWeight; + } + + /// + /// Gets a number between 0 and 1 that indicates the overall installation progress. + /// + public double Progress { get; private set; } + + public void ProcessMessage(InstallMessage messageType, Record messageRecord) + { + // This MSI progress-handling code was mostly borrowed from burn and translated from C++ to C#. + + switch (messageType) + { + case InstallMessage.ActionStart: + if (this.enableActionData) + { + this.enableActionData = false; + } + break; + + case InstallMessage.ActionData: + if (this.enableActionData) + { + if (this.moveForward) + { + this.completed += this.step; + } + else + { + this.completed -= this.step; + } + + this.UpdateProgress(); + } + break; + + case InstallMessage.Progress: + this.ProcessProgressMessage(messageRecord); + break; + } + } + + private void ProcessProgressMessage(Record progressRecord) + { + // This MSI progress-handling code was mostly borrowed from burn and translated from C++ to C#. + + if (progressRecord == null || progressRecord.FieldCount == 0) + { + return; + } + + int fieldCount = progressRecord.FieldCount; + int progressType = progressRecord.GetInteger(1); + string progressTypeString = String.Empty; + switch (progressType) + { + case 0: // Master progress reset + if (fieldCount < 4) + { + return; + } + + this.progressPhase++; + + this.total = progressRecord.GetInteger(2); + if (this.progressPhase == 1) + { + // HACK!!! this is a hack courtesy of the Windows Installer team. It seems the script planning phase + // is always off by "about 50". So we'll toss an extra 50 ticks on so that the standard progress + // doesn't go over 100%. If there are any custom actions, they may blow the total so we'll call this + // "close" and deal with the rest. + this.total += 50; + } + + this.moveForward = (progressRecord.GetInteger(3) == 0); + this.completed = (this.moveForward ? 0 : this.total); // if forward start at 0, if backwards start at max + this.enableActionData = false; + + this.UpdateProgress(); + break; + + case 1: // Action info + if (fieldCount < 3) + { + return; + } + + if (progressRecord.GetInteger(3) == 0) + { + this.enableActionData = false; + } + else + { + this.enableActionData = true; + this.step = progressRecord.GetInteger(2); + } + break; + + case 2: // Progress report + if (fieldCount < 2 || this.total == 0 || this.progressPhase == 0) + { + return; + } + + if (this.moveForward) + { + this.completed += progressRecord.GetInteger(2); + } + else + { + this.completed -= progressRecord.GetInteger(2); + } + + this.UpdateProgress(); + break; + + case 3: // Progress total addition + this.total += progressRecord.GetInteger(2); + break; + } + } + + private void UpdateProgress() + { + if (this.progressPhase < 1 || this.total == 0) + { + this.Progress = 0; + } + else if (this.progressPhase == 1) + { + this.Progress = this.scriptPhaseWeight * Math.Min(this.completed, this.total) / this.total; + } + else if (this.progressPhase == 2) + { + this.Progress = this.scriptPhaseWeight + + (1 - this.scriptPhaseWeight) * Math.Min(this.completed, this.total) / this.total; + } + else + { + this.Progress = 1; + } + } + } +} -- cgit v1.2.3-55-g6feb