summaryrefslogtreecommitdiff
path: root/src/tools/heat/UtilHeatExtension.cs
diff options
context:
space:
mode:
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}