diff options
author | Rob Mensching <rob@firegiant.com> | 2022-07-26 17:20:39 -0700 |
---|---|---|
committer | Rob Mensching <rob@firegiant.com> | 2022-08-01 20:25:19 -0700 |
commit | a627ca9b720047e633a8fe72003ab9bee31006c5 (patch) | |
tree | 2bc8a924bb4141ab718e74d08f6459a0ffe8d573 /src/tools/heat/UtilHeatExtension.cs | |
parent | 521eb3c9cf38823a2c4019abb85dc0b3200b92cb (diff) | |
download | wix-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.cs | 389 |
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 | |||
3 | namespace 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 | } | ||