diff options
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 | } | ||