aboutsummaryrefslogtreecommitdiff
path: root/src/tools/heat/UtilHeatExtension.cs
diff options
context:
space:
mode:
authorRob Mensching <rob@firegiant.com>2022-07-26 17:20:39 -0700
committerRob Mensching <rob@firegiant.com>2022-08-01 20:25:19 -0700
commita627ca9b720047e633a8fe72003ab9bee31006c5 (patch)
tree2bc8a924bb4141ab718e74d08f6459a0ffe8d573 /src/tools/heat/UtilHeatExtension.cs
parent521eb3c9cf38823a2c4019abb85dc0b3200b92cb (diff)
downloadwix-a627ca9b720047e633a8fe72003ab9bee31006c5.tar.gz
wix-a627ca9b720047e633a8fe72003ab9bee31006c5.tar.bz2
wix-a627ca9b720047e633a8fe72003ab9bee31006c5.zip
Create WixToolset.Heat.nupkg to distribute heat.exe and Heat targets
Moves Heat functionality to the "tools" layer and packages it all up in WixToolset.Heat.nupkg for distribution in WiX v4. Completes 6838
Diffstat (limited to 'src/tools/heat/UtilHeatExtension.cs')
-rw-r--r--src/tools/heat/UtilHeatExtension.cs389
1 files changed, 389 insertions, 0 deletions
diff --git a/src/tools/heat/UtilHeatExtension.cs b/src/tools/heat/UtilHeatExtension.cs
new file mode 100644
index 00000000..469e38b5
--- /dev/null
+++ b/src/tools/heat/UtilHeatExtension.cs
@@ -0,0 +1,389 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixToolset.Harvesters
4{
5 using System;
6 using System.Collections.Generic;
7 using System.IO;
8 using WixToolset.Data;
9 using WixToolset.Harvesters.Data;
10 using WixToolset.Harvesters.Extensibility;
11
12 /// <summary>
13 /// A utility heat extension for the WiX Toolset Harvester application.
14 /// </summary>
15 public sealed class UtilHeatExtension : BaseHeatExtension
16 {
17 public UtilHeatExtension(IServiceProvider serviceProvider)
18 {
19 }
20
21 /// <summary>
22 /// Gets the supported command line types for this extension.
23 /// </summary>
24 /// <value>The supported command line types for this extension.</value>
25 public override HeatCommandLineOption[] CommandLineTypes
26 {
27 get
28 {
29 return new HeatCommandLineOption[]
30 {
31 new HeatCommandLineOption("dir", "harvest a directory"),
32 new HeatCommandLineOption("file", "harvest a file"),
33 new HeatCommandLineOption("perf", "harvest performance counters"),
34 new HeatCommandLineOption("reg", "harvest a .reg file"),
35 new HeatCommandLineOption("-ag", "autogenerate component guids at compile time"),
36 new HeatCommandLineOption("-cg <ComponentGroupName>", "component group name (cannot contain spaces e.g -cg MyComponentGroup)"),
37 new HeatCommandLineOption("-dr <DirectoryName>", "directory reference to root directories (cannot contain spaces e.g. -dr MyAppDirRef)"),
38 new HeatCommandLineOption("-var <VariableName>", "substitute File/@Source=\"SourceDir\" with a preprocessor or a wix variable" + Environment.NewLine +
39 "(e.g. -var var.MySource will become File/@Source=\"$(var.MySource)\\myfile.txt\" and " + Environment.NewLine +
40 "-var wix.MySource will become File/@Source=\"!(wix.MySource)\\myfile.txt\""),
41 new HeatCommandLineOption("-gg", "generate guids now"),
42 new HeatCommandLineOption("-g1", "generated guids are not in brackets"),
43 new HeatCommandLineOption("-ke", "keep empty directories"),
44 new HeatCommandLineOption("-scom", "suppress COM elements"),
45 new HeatCommandLineOption("-sfrag", "suppress fragments"),
46 new HeatCommandLineOption("-srd", "suppress harvesting the root directory as an element"),
47 new HeatCommandLineOption("-svb6", "suppress VB6 COM elements"),
48 new HeatCommandLineOption("-sreg", "suppress registry harvesting"),
49 new HeatCommandLineOption("-suid", "suppress unique identifiers for files, components, & directories"),
50 new HeatCommandLineOption("-t", "transform harvested output with XSL file"),
51 new HeatCommandLineOption("-template", "use template, one of: fragment,module,product"),
52 };
53 }
54 }
55
56 /// <summary>
57 /// Parse the command line options for this extension.
58 /// </summary>
59 /// <param name="type">The active harvester type.</param>
60 /// <param name="args">The option arguments.</param>
61 public override void ParseOptions(string type, string[] args)
62 {
63 bool active = false;
64 IHarvesterExtension harvesterExtension = null;
65 bool suppressHarvestingRegistryValues = false;
66 UtilFinalizeHarvesterMutator utilFinalizeHarvesterMutator = new UtilFinalizeHarvesterMutator();
67 UtilMutator utilMutator = new UtilMutator();
68 List<UtilTransformMutator> transformMutators = new List<UtilTransformMutator>();
69 GenerateType generateType = GenerateType.Components;
70
71 // select the harvester
72 switch (type)
73 {
74 case "dir":
75 harvesterExtension = new DirectoryHarvester();
76 active = true;
77 break;
78 case "file":
79 harvesterExtension = new FileHarvester();
80 active = true;
81 break;
82 case "perf":
83 harvesterExtension = new PerformanceCategoryHarvester();
84 active = true;
85 break;
86 case "reg":
87 harvesterExtension = new RegFileHarvester();
88 active = true;
89 break;
90 }
91
92 // set default settings
93 utilMutator.CreateFragments = true;
94 utilMutator.SetUniqueIdentifiers = true;
95
96 // parse the options
97 for (int i = 0; i < args.Length; i++)
98 {
99 string commandSwitch = args[i];
100
101 if (null == commandSwitch || 0 == commandSwitch.Length) // skip blank arguments
102 {
103 continue;
104 }
105
106 if ('-' == commandSwitch[0] || '/' == commandSwitch[0])
107 {
108 string truncatedCommandSwitch = commandSwitch.Substring(1);
109
110 if ("ag" == truncatedCommandSwitch)
111 {
112 utilMutator.AutogenerateGuids = true;
113 }
114 else if ("cg" == truncatedCommandSwitch)
115 {
116 utilMutator.ComponentGroupName = this.GetArgumentParameter(args, i);
117
118 if (this.Core.Messaging.EncounteredError)
119 {
120 return;
121 }
122 }
123 else if ("dr" == truncatedCommandSwitch)
124 {
125 string dr = this.GetArgumentParameter(args, i);
126
127 if (this.Core.Messaging.EncounteredError)
128 {
129 return;
130 }
131
132 if (harvesterExtension is DirectoryHarvester)
133 {
134 ((DirectoryHarvester)harvesterExtension).RootedDirectoryRef = dr;
135 }
136 else if (harvesterExtension is FileHarvester)
137 {
138 ((FileHarvester)harvesterExtension).RootedDirectoryRef = dr;
139 }
140 }
141 else if ("gg" == truncatedCommandSwitch)
142 {
143 utilMutator.GenerateGuids = true;
144 }
145 else if ("g1" == truncatedCommandSwitch)
146 {
147 utilMutator.GuidFormat = "D";
148 }
149 else if ("ke" == truncatedCommandSwitch)
150 {
151 if (harvesterExtension is DirectoryHarvester)
152 {
153 ((DirectoryHarvester)harvesterExtension).KeepEmptyDirectories = true;
154 }
155 else if (active)
156 {
157 // TODO: error message - not applicable to file harvester
158 }
159 }
160 else if ("scom" == truncatedCommandSwitch)
161 {
162 if (active)
163 {
164 utilFinalizeHarvesterMutator.SuppressCOMElements = true;
165 }
166 else
167 {
168 // TODO: error message - not applicable
169 }
170 }
171 else if ("svb6" == truncatedCommandSwitch)
172 {
173 if (active)
174 {
175 utilFinalizeHarvesterMutator.SuppressVB6COMElements = true;
176 }
177 else
178 {
179 // TODO: error message - not applicable
180 }
181 }
182 else if ("sfrag" == truncatedCommandSwitch)
183 {
184 utilMutator.CreateFragments = false;
185 }
186 else if ("srd" == truncatedCommandSwitch)
187 {
188 if (harvesterExtension is DirectoryHarvester)
189 {
190 ((DirectoryHarvester)harvesterExtension).SuppressRootDirectory = true;
191 }
192 else if (harvesterExtension is FileHarvester)
193 {
194 ((FileHarvester)harvesterExtension).SuppressRootDirectory = true;
195 }
196 }
197 else if ("sreg" == truncatedCommandSwitch)
198 {
199 suppressHarvestingRegistryValues = true;
200 }
201 else if ("suid" == truncatedCommandSwitch)
202 {
203 utilMutator.SetUniqueIdentifiers = false;
204
205 if (harvesterExtension is DirectoryHarvester)
206 {
207 ((DirectoryHarvester)harvesterExtension).SetUniqueIdentifiers = false;
208 }
209 else if (harvesterExtension is FileHarvester)
210 {
211 ((FileHarvester)harvesterExtension).SetUniqueIdentifiers = false;
212 }
213 }
214 else if (truncatedCommandSwitch.StartsWith("t:", StringComparison.Ordinal) || "t" == truncatedCommandSwitch)
215 {
216 string xslFile;
217 if (truncatedCommandSwitch.StartsWith("t:", StringComparison.Ordinal))
218 {
219 this.Core.Messaging.Write(WarningMessages.DeprecatedCommandLineSwitch("t:", "t"));
220 xslFile = truncatedCommandSwitch.Substring(2);
221 }
222 else
223 {
224 xslFile = this.GetArgumentParameter(args, i, true);
225 }
226
227 if (0 <= xslFile.IndexOf('\"'))
228 {
229 this.Core.Messaging.Write(ErrorMessages.PathCannotContainQuote(xslFile));
230 return;
231 }
232
233 try
234 {
235 xslFile = Path.GetFullPath(xslFile);
236 }
237 catch (Exception e)
238 {
239 this.Core.Messaging.Write(ErrorMessages.InvalidCommandLineFileName(xslFile, e.Message));
240 return;
241 }
242
243 transformMutators.Add(new UtilTransformMutator(xslFile, transformMutators.Count));
244 }
245 else if (truncatedCommandSwitch.StartsWith("template:", StringComparison.Ordinal) || "template" == truncatedCommandSwitch)
246 {
247 string template;
248 if(truncatedCommandSwitch.StartsWith("template:", StringComparison.Ordinal))
249 {
250 this.Core.Messaging.Write(WarningMessages.DeprecatedCommandLineSwitch("template:", "template"));
251 template = truncatedCommandSwitch.Substring(9);
252 }
253 else
254 {
255 template = this.GetArgumentParameter(args, i);
256 }
257
258 switch (template)
259 {
260 case "fragment":
261 utilMutator.TemplateType = TemplateType.Fragment;
262 break;
263 case "module":
264 utilMutator.TemplateType = TemplateType.Module;
265 break;
266 case "product":
267 utilMutator.TemplateType = TemplateType.Package ;
268 break;
269 default:
270 // TODO: error
271 break;
272 }
273 }
274 else if ("var" == truncatedCommandSwitch)
275 {
276 if (active)
277 {
278 utilFinalizeHarvesterMutator.PreprocessorVariable = this.GetArgumentParameter(args, i);
279
280 if (this.Core.Messaging.EncounteredError)
281 {
282 return;
283 }
284 }
285 }
286 else if ("generate" == truncatedCommandSwitch)
287 {
288 if (harvesterExtension is DirectoryHarvester)
289 {
290 string genType = this.GetArgumentParameter(args, i).ToUpperInvariant();
291 switch (genType)
292 {
293 case "COMPONENTS":
294 generateType = GenerateType.Components;
295 break;
296 case "PAYLOADGROUP":
297 generateType = GenerateType.PayloadGroup;
298 break;
299 default:
300 throw new WixException(HarvesterErrors.InvalidDirectoryOutputType(genType));
301 }
302 }
303 else
304 {
305 // TODO: error message - not applicable
306 }
307 }
308 }
309 }
310
311 // set the appropriate harvester extension
312 if (active)
313 {
314 this.Core.Harvester.Extension = harvesterExtension;
315
316 if (!suppressHarvestingRegistryValues)
317 {
318 this.Core.Mutator.AddExtension(new UtilHarvesterMutator());
319 }
320
321 this.Core.Mutator.AddExtension(utilFinalizeHarvesterMutator);
322
323 if (harvesterExtension is DirectoryHarvester directoryHarvester)
324 {
325 directoryHarvester.GenerateType = generateType;
326 this.Core.Harvester.Core.RootDirectory = this.Core.Harvester.Core.ExtensionArgument;
327 }
328 else if (harvesterExtension is FileHarvester)
329 {
330 if (((FileHarvester)harvesterExtension).SuppressRootDirectory)
331 {
332 this.Core.Harvester.Core.RootDirectory = Path.GetDirectoryName(Path.GetFullPath(this.Core.Harvester.Core.ExtensionArgument));
333 }
334 else
335 {
336 this.Core.Harvester.Core.RootDirectory = Path.GetDirectoryName(Path.GetDirectoryName(Path.GetFullPath(this.Core.Harvester.Core.ExtensionArgument)));
337
338 // GetDirectoryName() returns null for root paths such as "c:\", so make sure to support that as well
339 if (null == this.Core.Harvester.Core.RootDirectory)
340 {
341 this.Core.Harvester.Core.RootDirectory = Path.GetPathRoot(Path.GetDirectoryName(Path.GetFullPath(this.Core.Harvester.Core.ExtensionArgument)));
342 }
343 }
344 }
345 }
346
347 // set the mutator
348 this.Core.Mutator.AddExtension(utilMutator);
349
350 // add the transforms
351 foreach (UtilTransformMutator transformMutator in transformMutators)
352 {
353 this.Core.Mutator.AddExtension(transformMutator);
354 }
355 }
356
357 private string GetArgumentParameter(string[] args, int index)
358 {
359 return this.GetArgumentParameter(args, index, false);
360 }
361
362 private string GetArgumentParameter(string[] args, int index, bool allowSpaces)
363 {
364 string truncatedCommandSwitch = args[index];
365 string commandSwitchValue = args[index + 1];
366
367 //increment the index to the switch value
368 index++;
369
370 if (IsValidArg(args, index) && !String.IsNullOrEmpty(commandSwitchValue.Trim()))
371 {
372 if (!allowSpaces && commandSwitchValue.Contains(" "))
373 {
374 this.Core.Messaging.Write(HarvesterErrors.SpacesNotAllowedInArgumentValue(truncatedCommandSwitch, commandSwitchValue));
375 }
376 else
377 {
378 return commandSwitchValue;
379 }
380 }
381 else
382 {
383 this.Core.Messaging.Write(HarvesterErrors.ArgumentRequiresValue(truncatedCommandSwitch));
384 }
385
386 return null;
387 }
388 }
389}