aboutsummaryrefslogtreecommitdiff
path: root/src/light/light.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/light/light.cs')
-rw-r--r--src/light/light.cs574
1 files changed, 0 insertions, 574 deletions
diff --git a/src/light/light.cs b/src/light/light.cs
deleted file mode 100644
index 0f467bbb..00000000
--- a/src/light/light.cs
+++ /dev/null
@@ -1,574 +0,0 @@
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.Tools
4{
5 using System;
6 using System.Collections.Generic;
7 using System.Globalization;
8 using System.IO;
9 using System.Linq;
10 using System.Runtime.InteropServices;
11 using System.Text;
12 using System.Threading;
13 using WixToolset.Core;
14 using WixToolset.Data;
15 using WixToolset.Data.Bind;
16 using WixToolset.Extensibility;
17 using WixToolset.Extensibility.Services;
18
19 /// <summary>
20 /// The main entry point for light.
21 /// </summary>
22 public sealed class Light
23 {
24 LightCommandLine commandLine;
25 //private IEnumerable<IBinderExtension> binderExtensions;
26 //private IEnumerable<IBinderFileManager> fileManagers;
27
28 /// <summary>
29 /// The main entry point for light.
30 /// </summary>
31 /// <param name="args">Commandline arguments for the application.</param>
32 /// <returns>Returns the application error code.</returns>
33 [MTAThread]
34 public static int Main(string[] args)
35 {
36 var serviceProvider = new WixToolsetServiceProvider();
37
38 var listener = new ConsoleMessageListener("WIX", "light.exe");
39
40 Light light = new Light();
41 return light.Run(serviceProvider, listener, args);
42 }
43
44 /// <summary>
45 /// Main running method for the application.
46 /// </summary>
47 /// <param name="args">Commandline arguments to the application.</param>
48 /// <returns>Returns the application error code.</returns>
49 public int Run(IServiceProvider serviceProvider, IMessageListener listener, string[] args)
50 {
51 var messaging = serviceProvider.GetService<IMessaging>();
52 messaging.SetListener(listener);
53
54 try
55 {
56 var unparsed = this.ParseCommandLineAndLoadExtensions(serviceProvider, messaging, args);
57
58 if (!messaging.EncounteredError)
59 {
60 if (this.commandLine.ShowLogo)
61 {
62 AppCommon.DisplayToolHeader();
63 }
64
65 if (this.commandLine.ShowHelp)
66 {
67 PrintHelp();
68 AppCommon.DisplayToolFooter();
69 }
70 else
71 {
72 foreach (string arg in unparsed)
73 {
74 messaging.Write(WarningMessages.UnsupportedCommandLineArgument(arg));
75 }
76
77 this.Bind(serviceProvider, messaging);
78 }
79 }
80 }
81 catch (WixException we)
82 {
83 messaging.Write(we.Error);
84 }
85 catch (Exception e)
86 {
87 messaging.Write(ErrorMessages.UnexpectedException(e.Message, e.GetType().ToString(), e.StackTrace));
88 if (e is NullReferenceException || e is SEHException)
89 {
90 throw;
91 }
92 }
93
94 return messaging.LastErrorNumber;
95 }
96
97 /// <summary>
98 /// Parse command line and load all the extensions.
99 /// </summary>
100 /// <param name="args">Command line arguments to be parsed.</param>
101 private IEnumerable<string> ParseCommandLineAndLoadExtensions(IServiceProvider serviceProvider, IMessaging messaging, string[] args)
102 {
103 var arguments = serviceProvider.GetService<ICommandLineArguments>();
104 arguments.Populate(args);
105
106 var extensionManager = CreateExtensionManagerWithStandardBackends(serviceProvider, arguments.Extensions);
107
108 var context = serviceProvider.GetService<ICommandLineContext>();
109 context.ExtensionManager = extensionManager;
110 context.Messaging = messaging;
111 context.Arguments = arguments;
112
113 this.commandLine = new LightCommandLine(messaging);
114 var unprocessed = this.commandLine.Parse(context);
115
116 return unprocessed;
117 }
118
119 private void Bind(IServiceProvider serviceProvider, IMessaging messaging)
120 {
121 var output = this.LoadWixout(messaging);
122
123 if (messaging.EncounteredError)
124 {
125 return;
126 }
127
128 var intermediateFolder = this.commandLine.IntermediateFolder;
129 if (String.IsNullOrEmpty(intermediateFolder))
130 {
131 intermediateFolder = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
132 }
133
134 var localizations = this.LoadLocalizationFiles(messaging, this.commandLine.LocalizationFiles);
135
136 if (messaging.EncounteredError)
137 {
138 return;
139 }
140
141 ResolveResult resolveResult;
142 {
143 var resolver = new Resolver(serviceProvider);
144 resolver.BindPaths = this.commandLine.BindPaths;
145 resolver.IntermediateFolder = intermediateFolder;
146 resolver.IntermediateRepresentation = output;
147 resolver.Localizations = localizations;
148
149 resolveResult = resolver.Execute();
150 }
151
152 if (messaging.EncounteredError)
153 {
154 return;
155 }
156
157 BindResult bindResult;
158 {
159 var binder = new Binder(serviceProvider);
160 binder.CabbingThreadCount = this.commandLine.CabbingThreadCount;
161 binder.CabCachePath = this.commandLine.CabCachePath;
162 binder.Codepage = resolveResult.Codepage;
163 binder.DefaultCompressionLevel = this.commandLine.DefaultCompressionLevel;
164 binder.DelayedFields = resolveResult.DelayedFields;
165 binder.ExpectedEmbeddedFiles = resolveResult.ExpectedEmbeddedFiles;
166 binder.Ices = this.commandLine.Ices;
167 binder.IntermediateFolder = intermediateFolder;
168 binder.IntermediateRepresentation = resolveResult.IntermediateRepresentation;
169 binder.OutputPath = this.commandLine.OutputFile;
170 binder.OutputPdbPath = Path.ChangeExtension(this.commandLine.OutputFile, ".wixpdb");
171 binder.SuppressIces = this.commandLine.SuppressIces;
172 binder.SuppressValidation = this.commandLine.SuppressValidation;
173
174 bindResult = binder.Execute();
175 }
176
177 if (messaging.EncounteredError)
178 {
179 return;
180 }
181
182 {
183 var layout = new Layout(serviceProvider);
184 layout.FileTransfers = bindResult.FileTransfers;
185 layout.ContentFilePaths = bindResult.ContentFilePaths;
186 layout.ContentsFile = this.commandLine.ContentsFile;
187 layout.OutputsFile = this.commandLine.OutputsFile;
188 layout.BuiltOutputsFile = this.commandLine.BuiltOutputsFile;
189 layout.SuppressAclReset = this.commandLine.SuppressAclReset;
190
191 layout.Execute();
192 }
193 }
194
195 private void Run(IMessaging messaging)
196 {
197#if false
198 // Initialize the variable resolver from the command line.
199 WixVariableResolver wixVariableResolver = new WixVariableResolver();
200 foreach (var wixVar in this.commandLine.Variables)
201 {
202 wixVariableResolver.AddVariable(wixVar.Key, wixVar.Value);
203 }
204
205 // Initialize the linker from the command line.
206 Linker linker = new Linker();
207 linker.UnreferencedSymbolsFile = this.commandLine.UnreferencedSymbolsFile;
208 linker.ShowPedanticMessages = this.commandLine.ShowPedanticMessages;
209 linker.WixVariableResolver = wixVariableResolver;
210
211 foreach (IExtensionData data in this.extensionData)
212 {
213 linker.AddExtensionData(data);
214 }
215
216 // Initialize the binder from the command line.
217 WixToolset.Binder binder = new WixToolset.Binder();
218 binder.CabCachePath = this.commandLine.CabCachePath;
219 binder.ContentsFile = this.commandLine.ContentsFile;
220 binder.BuiltOutputsFile = this.commandLine.BuiltOutputsFile;
221 binder.OutputsFile = this.commandLine.OutputsFile;
222 binder.WixprojectFile = this.commandLine.WixprojectFile;
223 binder.BindPaths.AddRange(this.commandLine.BindPaths);
224 binder.CabbingThreadCount = this.commandLine.CabbingThreadCount;
225 if (this.commandLine.DefaultCompressionLevel.HasValue)
226 {
227 binder.DefaultCompressionLevel = this.commandLine.DefaultCompressionLevel.Value;
228 }
229 binder.Ices.AddRange(this.commandLine.Ices);
230 binder.SuppressIces.AddRange(this.commandLine.SuppressIces);
231 binder.SuppressAclReset = this.commandLine.SuppressAclReset;
232 binder.SuppressLayout = this.commandLine.SuppressLayout;
233 binder.SuppressValidation = this.commandLine.SuppressValidation;
234 binder.PdbFile = this.commandLine.SuppressWixPdb ? null : this.commandLine.PdbFile;
235 binder.TempFilesLocation = AppCommon.GetTempLocation();
236 binder.WixVariableResolver = wixVariableResolver;
237
238 foreach (IBinderExtension extension in this.binderExtensions)
239 {
240 binder.AddExtension(extension);
241 }
242
243 foreach (IBinderFileManager fileManager in this.fileManagers)
244 {
245 binder.AddExtension(fileManager);
246 }
247
248 // Initialize the localizer.
249 Localizer localizer = this.InitializeLocalization(linker.TableDefinitions);
250 if (messaging.EncounteredError)
251 {
252 return;
253 }
254
255 wixVariableResolver.Localizer = localizer;
256 linker.Localizer = localizer;
257 binder.Localizer = localizer;
258
259 // Loop through all the believed object files.
260 List<Section> sections = new List<Section>();
261 Output output = null;
262 foreach (string inputFile in this.commandLine.Files)
263 {
264 string inputFileFullPath = Path.GetFullPath(inputFile);
265 FileFormat format = FileStructure.GuessFileFormatFromExtension(Path.GetExtension(inputFileFullPath));
266 bool retry;
267 do
268 {
269 retry = false;
270
271 try
272 {
273 switch (format)
274 {
275 case FileFormat.Wixobj:
276 Intermediate intermediate = Intermediate.Load(inputFileFullPath, linker.TableDefinitions, this.commandLine.SuppressVersionCheck);
277 sections.AddRange(intermediate.Sections);
278 break;
279
280 case FileFormat.Wixlib:
281 Library library = Library.Load(inputFileFullPath, linker.TableDefinitions, this.commandLine.SuppressVersionCheck);
282 AddLibraryLocalizationsToLocalizer(library, this.commandLine.Cultures, localizer);
283 sections.AddRange(library.Sections);
284 break;
285
286 default:
287 output = Output.Load(inputFileFullPath, this.commandLine.SuppressVersionCheck);
288 break;
289 }
290 }
291 catch (WixUnexpectedFileFormatException e)
292 {
293 format = e.FileFormat;
294 retry = (FileFormat.Wixobj == format || FileFormat.Wixlib == format || FileFormat.Wixout == format); // .wixobj, .wixout and .wixout are supported by light.
295 if (!retry)
296 {
297 messaging.OnMessage(e.Error);
298 }
299 }
300 } while (retry);
301 }
302
303 // Stop processing if any errors were found loading object files.
304 if (messaging.EncounteredError)
305 {
306 return;
307 }
308
309 // and now for the fun part
310 if (null == output)
311 {
312 OutputType expectedOutputType = OutputType.Unknown;
313 if (!String.IsNullOrEmpty(this.commandLine.OutputFile))
314 {
315 expectedOutputType = Output.GetOutputType(Path.GetExtension(this.commandLine.OutputFile));
316 }
317
318 output = linker.Link(sections, expectedOutputType);
319
320 // If an error occurred during linking, stop processing.
321 if (null == output)
322 {
323 return;
324 }
325 }
326 else if (0 != sections.Count)
327 {
328 throw new InvalidOperationException(LightStrings.EXP_CannotLinkObjFilesWithOutpuFile);
329 }
330
331 bool tidy = true; // clean up after ourselves by default.
332 try
333 {
334 // only output the xml if its a patch build or user specfied to only output wixout
335 string outputFile = this.commandLine.OutputFile;
336 string outputExtension = Path.GetExtension(outputFile);
337 if (this.commandLine.OutputXml || OutputType.Patch == output.Type)
338 {
339 if (String.IsNullOrEmpty(outputExtension) || outputExtension.Equals(".wix", StringComparison.Ordinal))
340 {
341 outputExtension = (OutputType.Patch == output.Type) ? ".wixmsp" : ".wixout";
342 outputFile = Path.ChangeExtension(outputFile, outputExtension);
343 }
344
345 output.Save(outputFile);
346 }
347 else // finish creating the MSI/MSM
348 {
349 if (String.IsNullOrEmpty(outputExtension) || outputExtension.Equals(".wix", StringComparison.Ordinal))
350 {
351 outputExtension = Output.GetExtension(output.Type);
352 outputFile = Path.ChangeExtension(outputFile, outputExtension);
353 }
354
355 binder.Bind(output, outputFile);
356 }
357 }
358 catch (WixException we) // keep files around for debugging IDT issues.
359 {
360 if (we is WixInvalidIdtException)
361 {
362 tidy = false;
363 }
364
365 throw;
366 }
367 catch (Exception) // keep files around for debugging unexpected exceptions.
368 {
369 tidy = false;
370 throw;
371 }
372 finally
373 {
374 if (null != binder)
375 {
376 binder.Cleanup(tidy);
377 }
378 }
379
380 return;
381#endif
382 }
383
384#if false
385 private Localizer InitializeLocalization(TableDefinitionCollection tableDefinitions)
386 {
387 Localizer localizer = null;
388
389 // Instantiate the localizer and load any localization files.
390 if (!this.commandLine.SuppressLocalization || 0 < this.commandLine.LocalizationFiles.Count || null != this.commandLine.Cultures || !this.commandLine.OutputXml)
391 {
392 List<Localization> localizations = new List<Localization>();
393
394 // Load each localization file.
395 foreach (string localizationFile in this.commandLine.LocalizationFiles)
396 {
397 Localization localization = Localizer.ParseLocalizationFile(localizationFile, tableDefinitions);
398 if (null != localization)
399 {
400 localizations.Add(localization);
401 }
402 }
403
404 localizer = new Localizer();
405 if (null != this.commandLine.Cultures)
406 {
407 // Alocalizations in order specified in cultures.
408 foreach (string culture in this.commandLine.Cultures)
409 {
410 foreach (Localization localization in localizations)
411 {
412 if (culture.Equals(localization.Culture, StringComparison.OrdinalIgnoreCase))
413 {
414 localizer.AddLocalization(localization);
415 }
416 }
417 }
418 }
419 else // no cultures specified, so try neutral culture and if none of those add all loc files.
420 {
421 bool neutralFound = false;
422 foreach (Localization localization in localizations)
423 {
424 if (String.IsNullOrEmpty(localization.Culture))
425 {
426 // If a neutral wxl was provided use it.
427 localizer.AddLocalization(localization);
428 neutralFound = true;
429 }
430 }
431
432 if (!neutralFound)
433 {
434 // No cultures were specified and no neutral wxl are available, include all of the loc files.
435 foreach (Localization localization in localizations)
436 {
437 localizer.AddLocalization(localization);
438 }
439 }
440 }
441
442 // Load localizations provided by extensions with data.
443 foreach (IExtensionData data in this.extensionData)
444 {
445 Library library = data.GetLibrary(tableDefinitions);
446 if (null != library)
447 {
448 // Load the extension's default culture if it provides one and no cultures were specified.
449 string[] extensionCultures = this.commandLine.Cultures;
450 if (null == extensionCultures && null != data.DefaultCulture)
451 {
452 extensionCultures = new string[] { data.DefaultCulture };
453 }
454
455 AddLibraryLocalizationsToLocalizer(library, extensionCultures, localizer);
456 }
457 }
458 }
459
460 return localizer;
461 }
462
463 private void AddLibraryLocalizationsToLocalizer(Library library, string[] cultures, Localizer localizer)
464 {
465 foreach (Localization localization in library.GetLocalizations(cultures))
466 {
467 localizer.AddLocalization(localization);
468 }
469 }
470#endif
471
472 private bool TryParseCommandLineArgumentWithExtension(string arg, IEnumerable<IExtensionCommandLine> extensions)
473 {
474 foreach (var extension in extensions)
475 {
476 // TODO: decide what to do with "IParseCommandLine" argument.
477 if (extension.TryParseArgument(null, arg))
478 {
479 return true;
480 }
481 }
482
483 return false;
484 }
485
486 private IEnumerable<Localization> LoadLocalizationFiles(IMessaging messaging, IEnumerable<string> locFiles)
487 {
488 foreach (var loc in locFiles)
489 {
490 var localization = Localizer.ParseLocalizationFile(messaging, loc);
491
492 yield return localization;
493 }
494 }
495
496 private Intermediate LoadWixout(IMessaging messaging)
497 {
498 var path = this.commandLine.Files.Single();
499
500 return Intermediate.Load(path);
501 }
502
503 private static IExtensionManager CreateExtensionManagerWithStandardBackends(IServiceProvider serviceProvider, IEnumerable<string> extensions)
504 {
505 var extensionManager = serviceProvider.GetService<IExtensionManager>();
506
507 foreach (var type in new[] { typeof(WixToolset.Core.Burn.WixToolsetStandardBackend), typeof(WixToolset.Core.WindowsInstaller.WixToolsetStandardBackend) })
508 {
509 extensionManager.Add(type.Assembly);
510 }
511
512 foreach (var extension in extensions)
513 {
514 extensionManager.Load(extension);
515 }
516
517 return extensionManager;
518 }
519
520 private static void PrintHelp()
521 {
522 string lightArgs = LightStrings.CommandLineArguments;
523
524 Console.WriteLine(String.Format(LightStrings.HelpMessage, lightArgs));
525 }
526
527 private class ConsoleMessageListener : IMessageListener
528 {
529 public ConsoleMessageListener(string shortName, string longName)
530 {
531 this.ShortAppName = shortName;
532 this.LongAppName = longName;
533
534 PrepareConsoleForLocalization();
535 }
536
537 public string LongAppName { get; }
538
539 public string ShortAppName { get; }
540
541 public void Write(Message message)
542 {
543 var filename = message.SourceLineNumbers?.FileName ?? this.LongAppName;
544 var line = message.SourceLineNumbers?.LineNumber ?? -1;
545 var type = message.Level.ToString().ToLowerInvariant();
546 var output = message.Level >= MessageLevel.Warning ? Console.Out : Console.Error;
547
548 if (line > 0)
549 {
550 filename = String.Concat(filename, "(", line, ")");
551 }
552
553 output.WriteLine("{0} : {1} {2}{3:0000}: {4}", filename, type, this.ShortAppName, message.Id, message.ToString());
554 }
555
556 public void Write(string message)
557 {
558 Console.Out.WriteLine(message);
559 }
560
561 private static void PrepareConsoleForLocalization()
562 {
563 Thread.CurrentThread.CurrentUICulture = CultureInfo.CurrentUICulture.GetConsoleFallbackUICulture();
564
565 if (Console.OutputEncoding.CodePage != Encoding.UTF8.CodePage &&
566 Console.OutputEncoding.CodePage != Thread.CurrentThread.CurrentUICulture.TextInfo.OEMCodePage &&
567 Console.OutputEncoding.CodePage != Thread.CurrentThread.CurrentUICulture.TextInfo.ANSICodePage)
568 {
569 Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
570 }
571 }
572 }
573 }
574}