summaryrefslogtreecommitdiff
path: root/src/test/dtf/EmbeddedUI/InstallProgressCounter.cs
diff options
context:
space:
mode:
authorRob Mensching <rob@firegiant.com>2022-03-31 11:56:14 -0700
committerRob Mensching <rob@firegiant.com>2022-03-31 18:01:06 -0700
commit47582b162368e8edf7a3b11c13b8e9dabc5f0a26 (patch)
tree2c4063eff325684bed39de0edacd7866a257ae02 /src/test/dtf/EmbeddedUI/InstallProgressCounter.cs
parent167296c42497c4e95f0d5d71168542d747655981 (diff)
downloadwix-47582b162368e8edf7a3b11c13b8e9dabc5f0a26.tar.gz
wix-47582b162368e8edf7a3b11c13b8e9dabc5f0a26.tar.bz2
wix-47582b162368e8edf7a3b11c13b8e9dabc5f0a26.zip
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
Diffstat (limited to 'src/test/dtf/EmbeddedUI/InstallProgressCounter.cs')
-rw-r--r--src/test/dtf/EmbeddedUI/InstallProgressCounter.cs174
1 files changed, 174 insertions, 0 deletions
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 @@
1namespace WixToolset.Samples.EmbeddedUI
2{
3 using System;
4 using WixToolset.Dtf.WindowsInstaller;
5
6 /// <summary>
7 /// Tracks MSI progress messages and converts them to usable progress.
8 /// </summary>
9 public class InstallProgressCounter
10 {
11 private int total;
12 private int completed;
13 private int step;
14 private bool moveForward;
15 private bool enableActionData;
16 private int progressPhase;
17 private double scriptPhaseWeight;
18
19 public InstallProgressCounter() : this(0.3)
20 {
21 }
22
23 public InstallProgressCounter(double scriptPhaseWeight)
24 {
25 if (!(0 <= scriptPhaseWeight && scriptPhaseWeight <= 1))
26 {
27 throw new ArgumentOutOfRangeException("scriptPhaseWeight");
28 }
29
30 this.scriptPhaseWeight = scriptPhaseWeight;
31 }
32
33 /// <summary>
34 /// Gets a number between 0 and 1 that indicates the overall installation progress.
35 /// </summary>
36 public double Progress { get; private set; }
37
38 public void ProcessMessage(InstallMessage messageType, Record messageRecord)
39 {
40 // This MSI progress-handling code was mostly borrowed from burn and translated from C++ to C#.
41
42 switch (messageType)
43 {
44 case InstallMessage.ActionStart:
45 if (this.enableActionData)
46 {
47 this.enableActionData = false;
48 }
49 break;
50
51 case InstallMessage.ActionData:
52 if (this.enableActionData)
53 {
54 if (this.moveForward)
55 {
56 this.completed += this.step;
57 }
58 else
59 {
60 this.completed -= this.step;
61 }
62
63 this.UpdateProgress();
64 }
65 break;
66
67 case InstallMessage.Progress:
68 this.ProcessProgressMessage(messageRecord);
69 break;
70 }
71 }
72
73 private void ProcessProgressMessage(Record progressRecord)
74 {
75 // This MSI progress-handling code was mostly borrowed from burn and translated from C++ to C#.
76
77 if (progressRecord == null || progressRecord.FieldCount == 0)
78 {
79 return;
80 }
81
82 int fieldCount = progressRecord.FieldCount;
83 int progressType = progressRecord.GetInteger(1);
84 string progressTypeString = String.Empty;
85 switch (progressType)
86 {
87 case 0: // Master progress reset
88 if (fieldCount < 4)
89 {
90 return;
91 }
92
93 this.progressPhase++;
94
95 this.total = progressRecord.GetInteger(2);
96 if (this.progressPhase == 1)
97 {
98 // HACK!!! this is a hack courtesy of the Windows Installer team. It seems the script planning phase
99 // is always off by "about 50". So we'll toss an extra 50 ticks on so that the standard progress
100 // doesn't go over 100%. If there are any custom actions, they may blow the total so we'll call this
101 // "close" and deal with the rest.
102 this.total += 50;
103 }
104
105 this.moveForward = (progressRecord.GetInteger(3) == 0);
106 this.completed = (this.moveForward ? 0 : this.total); // if forward start at 0, if backwards start at max
107 this.enableActionData = false;
108
109 this.UpdateProgress();
110 break;
111
112 case 1: // Action info
113 if (fieldCount < 3)
114 {
115 return;
116 }
117
118 if (progressRecord.GetInteger(3) == 0)
119 {
120 this.enableActionData = false;
121 }
122 else
123 {
124 this.enableActionData = true;
125 this.step = progressRecord.GetInteger(2);
126 }
127 break;
128
129 case 2: // Progress report
130 if (fieldCount < 2 || this.total == 0 || this.progressPhase == 0)
131 {
132 return;
133 }
134
135 if (this.moveForward)
136 {
137 this.completed += progressRecord.GetInteger(2);
138 }
139 else
140 {
141 this.completed -= progressRecord.GetInteger(2);
142 }
143
144 this.UpdateProgress();
145 break;
146
147 case 3: // Progress total addition
148 this.total += progressRecord.GetInteger(2);
149 break;
150 }
151 }
152
153 private void UpdateProgress()
154 {
155 if (this.progressPhase < 1 || this.total == 0)
156 {
157 this.Progress = 0;
158 }
159 else if (this.progressPhase == 1)
160 {
161 this.Progress = this.scriptPhaseWeight * Math.Min(this.completed, this.total) / this.total;
162 }
163 else if (this.progressPhase == 2)
164 {
165 this.Progress = this.scriptPhaseWeight +
166 (1 - this.scriptPhaseWeight) * Math.Min(this.completed, this.total) / this.total;
167 }
168 else
169 {
170 this.Progress = 1;
171 }
172 }
173 }
174}