/// <summary> /// Load sections from the input files. /// </summary> /// <returns>Returns a section collection.</returns> private Dictionary <Section, string> LoadFragments() { // we need a Linker and the extensions for their table definitions Linker linker = new Linker(); linker.Message += new MessageEventHandler(this.Message); if (null != this.extensionList) { foreach (string extension in this.extensionList) { WixExtension wixExtension = WixExtension.Load(extension); linker.AddExtension(wixExtension); } } // load each intermediate and library file and get their sections Dictionary <Section, string> sectionFiles = new Dictionary <Section, string>(); if (null != this.inputFiles) { foreach (string inputFile in this.inputFiles) { string inputFileFullPath = Path.GetFullPath(inputFile); if (File.Exists(inputFileFullPath)) { // try loading as an object file try { Intermediate intermediate = Intermediate.Load(inputFileFullPath, linker.TableDefinitions, false, false); Generator.LoadSections(inputFile, sectionFiles, intermediate.Sections); continue; // next file } catch (WixNotIntermediateException) { // try another format } // try loading as a library file try { Library library = Library.Load(inputFileFullPath, linker.TableDefinitions, false, false); Generator.LoadSections(inputFile, sectionFiles, library.Sections); continue; // next file } catch (WixNotLibraryException) { this.OnMessage(LuxBuildErrors.CouldntLoadInput(inputFile)); } } } } return(sectionFiles); }
/// <summary> /// Main running method for the application. /// </summary> /// <param name="args">Commandline arguments to the application.</param> /// <returns>Returns the application error code.</returns> private int Run(string[] args) { Linker linker = null; Localizer localizer = null; SectionCollection sections = new SectionCollection(); ArrayList transforms = new ArrayList(); try { // parse the command line this.ParseCommandLine(args); // load any extensions List <WixExtension> loadedExtensionList = new List <WixExtension>(); foreach (string extension in this.extensionList) { WixExtension wixExtension = WixExtension.Load(extension); loadedExtensionList.Add(wixExtension); // If the extension provides a binder, use that now if it // matches the class from the command line. if (null != wixExtension.CustomBinder && null != this.binderClass && wixExtension.CustomBinder.GetType().Name.Equals(this.binderClass, StringComparison.Ordinal)) { this.binder = wixExtension.CustomBinder; } } // If a binder was specified, but not found then show an error. if (!String.IsNullOrEmpty(this.binderClass) && null == this.binder) { throw new WixException(WixErrors.SpecifiedBinderNotFound(this.binderClass)); } // create the linker, binder, and validator linker = new Linker(); if (null == this.binder) { this.binder = new Microsoft.Tools.WindowsInstallerXml.Binder(); } // have the binder parse the command line arguments light did not recognize string[] unparsedArgsArray = new string[this.unparsedArgs.Count]; this.unparsedArgs.CopyTo(unparsedArgsArray, 0); StringCollection remainingArgs = this.binder.ParseCommandLine(unparsedArgsArray, this.messageHandler); // Loop through the extensions to give them a shot at processing the remaining command-line args. foreach (WixExtension wixExtension in loadedExtensionList) { if (0 == remainingArgs.Count) { break; } remainingArgs = wixExtension.ParseCommandLine(remainingArgs, this.messageHandler); } this.ParseCommandLinePassTwo(remainingArgs); // exit if there was an error parsing the command line (otherwise the logo appears after error messages) if (this.messageHandler.EncounteredError) { return(this.messageHandler.LastErrorNumber); } foreach (string parameter in this.invalidArgs) { this.messageHandler.Display(this, WixWarnings.UnsupportedCommandLineArgument(parameter)); } this.invalidArgs = null; // exit if there was an error parsing the command line (otherwise the logo appears after error messages) if (this.messageHandler.EncounteredError) { return(this.messageHandler.LastErrorNumber); } if (0 == this.inputFiles.Count) { this.showHelp = true; } else if (null == this.outputFile) { if (1 < this.inputFiles.Count) { throw new WixException(WixErrors.MustSpecifyOutputWithMoreThanOneInput()); } this.outputFile = Path.ChangeExtension(Path.GetFileName(this.inputFiles[0]), ".wix"); // we'll let the linker change the extension later } this.binder.OutputFile = this.outputFile; this.binder.PostParseCommandLine(); if (this.showLogo) { AppCommon.DisplayToolHeader(); } if (this.showHelp) { this.PrintHelp(); AppCommon.DisplayToolFooter(); return(this.messageHandler.LastErrorNumber); } linker.AllowIdenticalRows = this.allowIdenticalRows; linker.AllowUnresolvedReferences = this.allowUnresolvedReferences; linker.Cultures = this.cultures; linker.UnreferencedSymbolsFile = this.unreferencedSymbolsFile; linker.ShowPedanticMessages = this.showPedanticMessages; linker.DropUnrealTables = this.dropUnrealTables; linker.SuppressLocalization = this.suppressLocalization; linker.SuppressMsiAssemblyTable = this.suppressMsiAssemblyTable; linker.WixVariableResolver = this.wixVariableResolver; // set the sequence suppression options linker.SuppressAdminSequence = this.suppressAdminSequence; linker.SuppressAdvertiseSequence = this.suppressAdvertiseSequence; linker.SuppressUISequence = this.suppressUISequence; linker.SectionIdOnRows = this.sectionIdOnRows; this.binder.TempFilesLocation = Environment.GetEnvironmentVariable("WIX_TEMP"); this.binder.WixVariableResolver = this.wixVariableResolver; if (null != this.bindPaths) { foreach (string bindPath in this.bindPaths) { if (-1 == bindPath.IndexOf('=')) { this.sourcePaths.Add(bindPath); } } } // instantiate the localizer and load any localization files if (!this.suppressLocalization || 0 < this.localizationFiles.Count || null != this.cultures || !this.outputXml) { List <Localization> localizations = new List <Localization>(); localizer = new Localizer(); localizer.Message += new MessageEventHandler(this.messageHandler.Display); // load each localization file foreach (string localizationFile in this.localizationFiles) { Localization localization = Localization.Load(localizationFile, linker.TableDefinitions, this.suppressSchema); localizations.Add(localization); } if (null != this.cultures) { // add localizations in order specified in cultures foreach (string culture in this.cultures) { foreach (Localization localization in localizations) { if (culture.Equals(localization.Culture, StringComparison.OrdinalIgnoreCase)) { localizer.AddLocalization(localization); } } } } else { bool neutralFound = false; foreach (Localization localization in localizations) { if (0 == localization.Culture.Length) { // if a neutral wxl was provided use it localizer.AddLocalization(localization); neutralFound = true; } } if (!neutralFound) { // cultures wasn't specified and no neutral wxl are available, include all of the files foreach (Localization localization in localizations) { localizer.AddLocalization(localization); } } } // immediately stop processing if any errors were found if (this.messageHandler.EncounteredError) { return(this.messageHandler.LastErrorNumber); } // tell all of the objects about the localizer linker.Localizer = localizer; this.binder.Localizer = localizer; this.wixVariableResolver.Localizer = localizer; } // process loaded extensions foreach (WixExtension wixExtension in loadedExtensionList) { linker.AddExtension(wixExtension); this.binder.AddExtension(wixExtension); // load the extension's localizations Library library = wixExtension.GetLibrary(linker.TableDefinitions); if (null != library) { // load the extension's default culture if it provides one and we don't specify any cultures string[] extensionCultures = this.cultures; if (null == extensionCultures && null != wixExtension.DefaultCulture) { extensionCultures = new string[] { wixExtension.DefaultCulture }; } library.GetLocalizations(extensionCultures, localizer); } } this.binder.ProcessExtensions(loadedExtensionList.ToArray()); // set the message handlers linker.Message += new MessageEventHandler(this.messageHandler.Display); this.binder.AddMessageEventHandler(new MessageEventHandler(this.messageHandler.Display)); Output output = null; // loop through all the believed object files foreach (string inputFile in this.inputFiles) { string dirName = Path.GetDirectoryName(inputFile); string inputFileFullPath = Path.GetFullPath(inputFile); if (!this.sourcePaths.Contains(dirName)) { this.sourcePaths.Add(dirName); } // try loading as an object file try { Intermediate intermediate = Intermediate.Load(inputFileFullPath, linker.TableDefinitions, this.suppressVersionCheck, this.suppressSchema); sections.AddRange(intermediate.Sections); continue; // next file } catch (WixNotIntermediateException) { // try another format } // try loading as a library file try { Library library = Library.Load(inputFileFullPath, linker.TableDefinitions, this.suppressVersionCheck, this.suppressSchema); library.GetLocalizations(this.cultures, localizer); sections.AddRange(library.Sections); continue; // next file } catch (WixNotLibraryException) { // try another format } // try loading as an output file output = Output.Load(inputFileFullPath, this.suppressVersionCheck, this.suppressSchema); } // immediately stop processing if any errors were found if (this.messageHandler.EncounteredError) { return(this.messageHandler.LastErrorNumber); } // set the binder file manager information foreach (string bindPath in this.bindPaths) { //Checking as IndexOf will return 0 if the string value is String.Empty. if (String.IsNullOrEmpty(bindPath)) { continue; } if (-1 == bindPath.IndexOf('=')) { this.binder.FileManager.BindPaths.Add(bindPath); } else { string[] namedPair = bindPath.Split('='); //It is ok to have duplicate key. this.binder.FileManager.NamedBindPaths.Add(namedPair[0], namedPair[1]); } } foreach (string sourcePath in this.sourcePaths) { this.binder.FileManager.SourcePaths.Add(sourcePath); } // and now for the fun part if (null == output) { OutputType expectedOutputType = OutputType.Unknown; if (this.outputFile != null) { expectedOutputType = Output.GetOutputType(Path.GetExtension(this.outputFile)); } output = linker.Link(sections, transforms, expectedOutputType); // if an error occurred during linking, stop processing if (null == output) { return(this.messageHandler.LastErrorNumber); } } else if (0 != sections.Count) { throw new InvalidOperationException(LightStrings.EXP_CannotLinkObjFilesWithOutpuFile); } // Now that the output object is either linked or loaded, tell the binder file manager about it. this.binder.FileManager.Output = output; // only output the xml if its a patch build or user specfied to only output wixout if (this.outputXml || OutputType.Patch == output.Type) { string outputExtension = Path.GetExtension(this.outputFile); if (null == outputExtension || 0 == outputExtension.Length || ".wix" == outputExtension) { if (OutputType.Patch == output.Type) { this.outputFile = Path.ChangeExtension(this.outputFile, ".wixmsp"); } else { this.outputFile = Path.ChangeExtension(this.outputFile, ".wixout"); } } output.Save(this.outputFile, (this.bindFiles ? this.binder.FileManager : null), this.wixVariableResolver, this.binder.TempFilesLocation); } else // finish creating the MSI/MSM { string outputExtension = Path.GetExtension(this.outputFile); if (null == outputExtension || 0 == outputExtension.Length || ".wix" == outputExtension) { outputExtension = Output.GetExtension(output.Type); this.outputFile = Path.ChangeExtension(this.outputFile, outputExtension); } this.binder.Bind(output, this.outputFile); } } catch (WixException we) { if (we is WixInvalidIdtException) { // make sure the IDT files stay around this.tidy = false; } this.messageHandler.Display(this, we.Error); } catch (Exception e) { // make sure the files stay around for debugging this.tidy = false; this.messageHandler.Display(this, WixErrors.UnexpectedException(e.Message, e.GetType().ToString(), e.StackTrace)); if (e is NullReferenceException || e is SEHException) { throw; } } finally { if (null != binder) { this.binder.Cleanup(this.tidy); } } return(this.messageHandler.LastErrorNumber); }
/// <summary> /// Main running method for the application. /// </summary> /// <param name="args">Commandline arguments to the application.</param> /// <returns>Returns the application error code.</returns> private int Run(string[] args) { try { XmlSchemaCollection objectSchema = new XmlSchemaCollection(); FileInfo currentFile = null; ArrayList intermediates = new ArrayList(); Linker linker = null; Microsoft.Tools.WindowsInstallerXml.Binder binder = null; Localizer localizer = null; try { // parse the command line this.ParseCommandLine(args); // exit if there was an error parsing the command line (otherwise the logo appears after error messages) if (this.messageHandler.FoundError) { return(this.messageHandler.PostProcess()); } if (0 == this.objectFiles.Count) { this.showHelp = true; } else if (null == this.outputFile) { if (1 < this.objectFiles.Count) { throw new ArgumentException("must specify output file when using more than one input file", "-out"); } FileInfo fi = (FileInfo)this.objectFiles[0]; this.outputFile = new FileInfo(Path.ChangeExtension(fi.Name, ".wix")); // we'll let the linker change the extension later } if (this.showLogo) { Assembly lightAssembly = Assembly.GetExecutingAssembly(); Console.WriteLine("Microsoft (R) Windows Installer Xml Linker version {0}", lightAssembly.GetName().Version.ToString()); Console.WriteLine("Copyright (C) Microsoft Corporation 2003. All rights reserved."); Console.WriteLine(); } if (this.showHelp) { Console.WriteLine(" usage: light.exe [-?] [-b basePath] [-nologo] [-out outputFile] objectFile [objectFile ...]"); Console.WriteLine(); Console.WriteLine(" -ai allow identical rows, identical rows will be treated as a warning"); Console.WriteLine(" -au (experimental) allow unresolved references, will not create a valid output"); Console.WriteLine(" -b base path to locate all files (default: current directory)"); Console.WriteLine(" -cc path to cache built cabinets (will not be deleted after linking)"); Console.WriteLine(" -ext extension (class, assembly), should extend SchemaExtension or BinderExtension"); Console.WriteLine(" -fv add a 'fileVersion' entry to the MsiAssemblyName table (rarely needed)"); Console.WriteLine(" -i specify the base output path for uncompressed images (default: -out parameter)"); Console.WriteLine(" -loc read localization string sfrom .wxl file"); Console.WriteLine(" -nologo skip printing light logo information"); Console.WriteLine(" -notidy do not delete temporary files (useful for debugging)"); Console.WriteLine(" -reusecab reuse cabinets from cabinet cache"); Console.WriteLine(" -out specify output file (default: write to current directory)"); Console.WriteLine(" -xo output xml instead of MSI format"); Console.WriteLine(" -pedantic:<level> pedantic checks (levels: easy, heroic, legendary)"); Console.WriteLine(" -reusecab reuse cabinets from cabinet cache"); Console.WriteLine(" -sa suppress assemblies: do not get assembly name information for assemblies"); Console.WriteLine(" -sacl suppress resetting ACLs (useful when laying out image to a network share)"); Console.WriteLine(" -sadmin suppress default admin sequence actions"); Console.WriteLine(" -sadv suppress default adv sequence actions"); Console.WriteLine(" -sa suppress assemblys: do not get assembly name information for assemblies"); Console.WriteLine(" -sf suppress files: do not get any file information (equivalent to -sa and -sh)"); Console.WriteLine(" -sh suppress file info: do not get hash, version, language, etc"); Console.WriteLine(" -sl suppress layout"); Console.WriteLine(" -ss suppress schema validation of documents (performance boost)"); Console.WriteLine(" -sui suppress default UI sequence actions"); Console.WriteLine(" -sv suppress intermediate file version mismatch checking"); Console.WriteLine(" -ts tag sectionId attribute on tuples (ignored if not used with -xo)"); Console.WriteLine(" -ust use small table definitions (for backwards compatiblity)"); Console.WriteLine(" -wx treat warnings as errors"); Console.WriteLine(" -w<N> set the warning level (0: show all, 3: show none)"); Console.WriteLine(" -sw suppress all warnings (same as -w3)"); Console.WriteLine(" -sw<N> suppress warning with specific message ID"); Console.WriteLine(" -v verbose output (same as -v2)"); Console.WriteLine(" -v<N> sets the level of verbose output (0: most output, 3: none)"); Console.WriteLine(" -? this help information"); Console.WriteLine(); Console.WriteLine("Environment variables:"); Console.WriteLine(" WIX_TEMP overrides the temporary directory used for cab creation, msm exploding, ..."); Console.WriteLine(); Console.WriteLine("Common extensions:"); Console.WriteLine(" .wxs - Windows installer Xml Source file"); Console.WriteLine(" .wxi - Windows installer Xml Include file"); Console.WriteLine(" .wxl - Windows installer Xml Localization file"); Console.WriteLine(" .wixobj - Windows installer Xml Object file (in XML format)"); Console.WriteLine(" .wixlib - Windows installer Xml Library file (in XML format)"); Console.WriteLine(" .wixout - Windows installer Xml Output file (in XML format)"); Console.WriteLine(); Console.WriteLine(" .msm - Windows installer Merge Module"); Console.WriteLine(" .msi - Windows installer Product Database"); Console.WriteLine(" .mst - Windows installer Transform"); Console.WriteLine(" .pcp - Windows installer Patch Creation Package"); Console.WriteLine(); Console.WriteLine("For more information see: http://wix.sourceforge.net"); return(this.messageHandler.PostProcess()); } // create the linker and the binder linker = new Linker(this.useSmallTables); binder = new Microsoft.Tools.WindowsInstallerXml.Binder(this.useSmallTables); linker.AllowIdenticalRows = this.allowIdenticalRows; linker.AllowUnresolvedReferences = this.allowUnresolvedReferences; linker.PedanticLevel = this.pedanticLevel; // set the sequence suppression options linker.SuppressAdminSequence = this.suppressAdminSequence; linker.SuppressAdvertiseSequence = this.suppressAdvertiseSequence; linker.SuppressUISequence = this.suppressUISequence; linker.SectionIdOnTuples = this.sectionIdOnTuples; binder.SuppressAclReset = this.suppressAclReset; binder.SetMsiAssemblyNameFileVersion = this.setMsiAssemblyNameFileVersion; binder.SuppressAssemblies = this.suppressAssemblies; binder.SuppressFileHashAndInfo = this.suppressFileHashAndInfo; if (this.suppressFiles) { binder.SuppressAssemblies = true; binder.SuppressFileHashAndInfo = true; } binder.SuppressLayout = this.suppressLayout; binder.TempFilesLocation = Environment.GetEnvironmentVariable("WIX_TEMP"); if (null != this.cabCachePath || this.reuseCabinets) { // ensure the cabinet cache path exists if we are going to use it if (null != this.cabCachePath && !Directory.Exists(this.cabCachePath)) { Directory.CreateDirectory(this.cabCachePath); } } if (null != this.basePaths) { foreach (string basePath in this.basePaths) { this.sourcePaths.Add(basePath); } } // load any extensions bool binderExtensionLoaded = false; foreach (string extension in this.extensionList) { Type extensionType = Type.GetType(extension); if (null == extensionType) { throw new WixInvalidExtensionException(extension); } if (extensionType.IsSubclassOf(typeof(BinderExtension))) { object[] extensionArgs = new object[] { this.basePaths, this.cabCachePath, this.reuseCabinets, this.sourcePaths }; BinderExtension binderExtension = Activator.CreateInstance(extensionType, extensionArgs) as BinderExtension; Debug.Assert(null != binderExtension); if (binderExtensionLoaded) { throw new ArgumentException(String.Format(CultureInfo.InvariantCulture, "cannot load binder extension: {0}. light can only load one binder extension and has already loaded binder extension: {1}.", binderExtension.ToString(), binder.Extension.ToString()), "ext"); } binder.Extension = binderExtension; binderExtensionLoaded = true; } else if (extensionType.IsSubclassOf(typeof(SchemaExtension))) { linker.AddExtension((SchemaExtension)Activator.CreateInstance(extensionType)); } else { throw new WixInvalidExtensionException(extension, extensionType, typeof(BinderExtension), typeof(SchemaExtension)); } } // if the binder extension has not been loaded yet use the built-in binder extension if (!binderExtensionLoaded) { binder.Extension = new LightBinderExtension(this.basePaths, this.cabCachePath, this.reuseCabinets, this.sourcePaths); } if (null != this.imagebaseOutputPath) { binder.ImageBaseOutputPath = this.imagebaseOutputPath; } // set the message handlers linker.Message += new MessageEventHandler(this.messageHandler.Display); binder.Message += new MessageEventHandler(this.messageHandler.Display); // load the object schema if (!this.suppressSchema) { Assembly wixAssembly = Assembly.Load("wix"); using (Stream objectsSchemaStream = wixAssembly.GetManifestResourceStream("Microsoft.Tools.WindowsInstallerXml.Xsd.objects.xsd")) { XmlReader reader = new XmlTextReader(objectsSchemaStream); objectSchema.Add("http://schemas.microsoft.com/wix/2003/04/objects", reader); } } Output output = null; // loop through all the believed object files foreach (FileInfo objectFile in this.objectFiles) { currentFile = objectFile; string dirName = Path.GetDirectoryName(currentFile.FullName); if (!StringArrayContains(this.sourcePaths, dirName)) { this.sourcePaths.Add(dirName); } // load the object file into an intermediate object and add it to the list to be linked using (Stream fileStream = new FileStream(currentFile.FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { XmlReader fileReader = new XmlTextReader(fileStream); try { XmlReader intermediateReader = fileReader; if (!this.suppressSchema) { intermediateReader = new XmlValidatingReader(fileReader); ((XmlValidatingReader)intermediateReader).Schemas.Add(objectSchema); } Intermediate intermediate = Intermediate.Load(intermediateReader, currentFile.FullName, linker.TableDefinitions, this.suppressVersionCheck); intermediates.Add(intermediate); continue; // next file } catch (WixNotIntermediateException) { // try another format } try { Library library = Library.Load(currentFile.FullName, linker.TableDefinitions, this.suppressVersionCheck); intermediates.AddRange(library.Intermediates); continue; // next file } catch (WixNotLibraryException) { // try another format } output = Output.Load(currentFile.FullName, this.suppressVersionCheck); } } // instantiate the localizer and load any wixloc files if (0 < this.localizationFiles.Count || !this.outputXml) { localizer = new Localizer(); localizer.Message += new MessageEventHandler(this.messageHandler.Display); // load each wixloc file foreach (string localizationFile in this.localizationFiles) { localizer.LoadFromFile(localizationFile); } // immediately stop processing if any errors were found if (this.messageHandler.FoundError) { return(this.messageHandler.PostProcess()); } } // and now for the fun part currentFile = this.outputFile; if (null == output) { // tell the linker about the localizer linker.Localizer = localizer; localizer = null; output = linker.Link((Intermediate[])intermediates.ToArray(typeof(Intermediate))); // if an error occurred during linking, stop processing if (null == output) { return(this.messageHandler.PostProcess()); } } else if (0 != intermediates.Count) { throw new InvalidOperationException("Cannot link object files (.wixobj) files with an output file (.wixout)"); } output.Path = this.outputFile.FullName; // only output the xml if (this.outputXml) { string outputExtension = Path.GetExtension(this.outputFile.FullName); if (null == outputExtension || 0 == outputExtension.Length || ".wix" == outputExtension) { output.Path = Path.ChangeExtension(this.outputFile.FullName, ".wixout"); } output.Save(); } else // finish creating the MSI/MSM { string outputExtension = Path.GetExtension(this.outputFile.FullName); if (null == outputExtension || 0 == outputExtension.Length || ".wix" == outputExtension) { if (OutputType.Module == output.Type) { output.Path = Path.ChangeExtension(this.outputFile.FullName, ".msm"); } else if (OutputType.PatchCreation == output.Type) { output.Path = Path.ChangeExtension(this.outputFile.FullName, ".pcp"); } else { output.Path = Path.ChangeExtension(this.outputFile.FullName, ".msi"); } } // tell the binder about the localizer binder.Localizer = localizer; binder.Bind(output); } currentFile = null; } catch (WixInvalidIdtException) { this.tidy = false; // make sure the IDT files stay around throw; } catch (WixMergeFailureException) { this.tidy = false; // make sure the merge.log stays around throw; } finally { if (null != binder) { if (this.tidy) { if (!binder.DeleteTempFiles()) { Console.WriteLine("Warning, failed to delete temporary directory: {0}", binder.TempFilesLocation); } } else { Console.WriteLine("Temporary directory located at '{0}'.", binder.TempFilesLocation); } } } } catch (WixException we) { // TODO: once all WixExceptions are converted to errors, this clause // should be a no-op that just catches WixFatalErrorException's this.messageHandler.Display("light.exe", "LGHT", we); return(1); } catch (Exception e) { this.OnMessage(WixErrors.UnexpectedException(e.Message, e.GetType().ToString(), e.StackTrace)); if (e is NullReferenceException || e is SEHException) { throw; } } return(this.messageHandler.PostProcess()); }
/// <summary> /// Main running method for the application. /// </summary> /// <param name="args">Commandline arguments to the application.</param> /// <returns>Returns the application error code.</returns> private int Run(string[] args) { Linker linker = null; Localizer localizer = null; SectionCollection sections = new SectionCollection(); ArrayList transforms = new ArrayList(); try { // parse the command line this.ParseCommandLine(args); // load any extensions List<WixExtension> loadedExtensionList = new List<WixExtension>(); foreach (string extension in this.extensionList) { WixExtension wixExtension = WixExtension.Load(extension); loadedExtensionList.Add(wixExtension); // If the extension provides a binder, use that now if it // matches the class from the command line. if (null != wixExtension.CustomBinder && null != this.binderClass && wixExtension.CustomBinder.GetType().Name.Equals(this.binderClass, StringComparison.Ordinal)) { this.binder = wixExtension.CustomBinder; } } // If a binder was specified, but not found then show an error. if (!String.IsNullOrEmpty(this.binderClass) && null == this.binder) { throw new WixException(WixErrors.SpecifiedBinderNotFound(this.binderClass)); } // create the linker, binder, and validator linker = new Linker(); if (null == this.binder) { this.binder = new Microsoft.Tools.WindowsInstallerXml.Binder(); } // have the binder parse the command line arguments light did not recognize string[] unparsedArgsArray = new string[this.unparsedArgs.Count]; this.unparsedArgs.CopyTo(unparsedArgsArray, 0); StringCollection remainingArgs = this.binder.ParseCommandLine(unparsedArgsArray, this.messageHandler); // Loop through the extensions to give them a shot at processing the remaining command-line args. foreach (WixExtension wixExtension in loadedExtensionList) { if (0 == remainingArgs.Count) { break; } remainingArgs = wixExtension.ParseCommandLine(remainingArgs, this.messageHandler); } this.ParseCommandLinePassTwo(remainingArgs); // exit if there was an error parsing the command line (otherwise the logo appears after error messages) if (this.messageHandler.EncounteredError) { return this.messageHandler.LastErrorNumber; } foreach (string parameter in this.invalidArgs) { this.messageHandler.Display(this, WixWarnings.UnsupportedCommandLineArgument(parameter)); } this.invalidArgs = null; // exit if there was an error parsing the command line (otherwise the logo appears after error messages) if (this.messageHandler.EncounteredError) { return this.messageHandler.LastErrorNumber; } if (0 == this.inputFiles.Count) { this.showHelp = true; } else if (null == this.outputFile) { if (1 < this.inputFiles.Count) { throw new WixException(WixErrors.MustSpecifyOutputWithMoreThanOneInput()); } this.outputFile = Path.ChangeExtension(Path.GetFileName(this.inputFiles[0]), ".wix"); // we'll let the linker change the extension later } this.binder.OutputFile = this.outputFile; this.binder.PostParseCommandLine(); if (this.showLogo) { AppCommon.DisplayToolHeader(); } if (this.showHelp) { this.PrintHelp(); AppCommon.DisplayToolFooter(); return this.messageHandler.LastErrorNumber; } linker.AllowIdenticalRows = this.allowIdenticalRows; linker.AllowUnresolvedReferences = this.allowUnresolvedReferences; linker.Cultures = this.cultures; linker.UnreferencedSymbolsFile = this.unreferencedSymbolsFile; linker.ShowPedanticMessages = this.showPedanticMessages; linker.DropUnrealTables = this.dropUnrealTables; linker.SuppressLocalization = this.suppressLocalization; linker.SuppressMsiAssemblyTable = this.suppressMsiAssemblyTable; linker.WixVariableResolver = this.wixVariableResolver; // set the sequence suppression options linker.SuppressAdminSequence = this.suppressAdminSequence; linker.SuppressAdvertiseSequence = this.suppressAdvertiseSequence; linker.SuppressUISequence = this.suppressUISequence; linker.SectionIdOnRows = this.sectionIdOnRows; this.binder.TempFilesLocation = Environment.GetEnvironmentVariable("WIX_TEMP"); this.binder.WixVariableResolver = this.wixVariableResolver; if (null != this.bindPaths) { foreach (string bindPath in this.bindPaths) { if (-1 == bindPath.IndexOf('=')) { this.sourcePaths.Add(bindPath); } } } // instantiate the localizer and load any localization files if (!this.suppressLocalization || 0 < this.localizationFiles.Count || null != this.cultures || !this.outputXml) { List<Localization> localizations = new List<Localization>(); localizer = new Localizer(); localizer.Message += new MessageEventHandler(this.messageHandler.Display); // load each localization file foreach (string localizationFile in this.localizationFiles) { Localization localization = Localization.Load(localizationFile, linker.TableDefinitions, this.suppressSchema); localizations.Add(localization); } if (null != this.cultures) { // add localizations in order specified in cultures foreach (string culture in this.cultures) { foreach (Localization localization in localizations) { if (culture.Equals(localization.Culture, StringComparison.OrdinalIgnoreCase)) { localizer.AddLocalization(localization); } } } } else { bool neutralFound = false; foreach (Localization localization in localizations) { if (0 == localization.Culture.Length) { // if a neutral wxl was provided use it localizer.AddLocalization(localization); neutralFound = true; } } if (!neutralFound) { // cultures wasn't specified and no neutral wxl are available, include all of the files foreach (Localization localization in localizations) { localizer.AddLocalization(localization); } } } // immediately stop processing if any errors were found if (this.messageHandler.EncounteredError) { return this.messageHandler.LastErrorNumber; } // tell all of the objects about the localizer linker.Localizer = localizer; this.binder.Localizer = localizer; this.wixVariableResolver.Localizer = localizer; } // process loaded extensions foreach (WixExtension wixExtension in loadedExtensionList) { linker.AddExtension(wixExtension); this.binder.AddExtension(wixExtension); // load the extension's localizations Library library = wixExtension.GetLibrary(linker.TableDefinitions); if (null != library) { // load the extension's default culture if it provides one and we don't specify any cultures string[] extensionCultures = this.cultures; if (null == extensionCultures && null != wixExtension.DefaultCulture) { extensionCultures = new string[] { wixExtension.DefaultCulture }; } library.GetLocalizations(extensionCultures, localizer); } } this.binder.ProcessExtensions(loadedExtensionList.ToArray()); // set the message handlers linker.Message += new MessageEventHandler(this.messageHandler.Display); this.binder.AddMessageEventHandler(new MessageEventHandler(this.messageHandler.Display)); Output output = null; // loop through all the believed object files foreach (string inputFile in this.inputFiles) { string dirName = Path.GetDirectoryName(inputFile); string inputFileFullPath = Path.GetFullPath(inputFile); if (!this.sourcePaths.Contains(dirName)) { this.sourcePaths.Add(dirName); } // try loading as an object file try { Intermediate intermediate = Intermediate.Load(inputFileFullPath, linker.TableDefinitions, this.suppressVersionCheck, this.suppressSchema); sections.AddRange(intermediate.Sections); continue; // next file } catch (WixNotIntermediateException) { // try another format } // try loading as a library file try { Library library = Library.Load(inputFileFullPath, linker.TableDefinitions, this.suppressVersionCheck, this.suppressSchema); library.GetLocalizations(this.cultures, localizer); sections.AddRange(library.Sections); continue; // next file } catch (WixNotLibraryException) { // try another format } // try loading as an output file output = Output.Load(inputFileFullPath, this.suppressVersionCheck, this.suppressSchema); } // immediately stop processing if any errors were found if (this.messageHandler.EncounteredError) { return this.messageHandler.LastErrorNumber; } // set the binder file manager information foreach (string bindPath in this.bindPaths) { //Checking as IndexOf will return 0 if the string value is String.Empty. if (String.IsNullOrEmpty(bindPath)) { continue; } if (-1 == bindPath.IndexOf('=')) { this.binder.FileManager.BindPaths.Add(bindPath); } else { string[] namedPair = bindPath.Split('='); //It is ok to have duplicate key. this.binder.FileManager.NamedBindPaths.Add(namedPair[0], namedPair[1]); } } foreach (string sourcePath in this.sourcePaths) { this.binder.FileManager.SourcePaths.Add(sourcePath); } // and now for the fun part if (null == output) { OutputType expectedOutputType = OutputType.Unknown; if (this.outputFile != null) { expectedOutputType = Output.GetOutputType(Path.GetExtension(this.outputFile)); } output = linker.Link(sections, transforms, expectedOutputType); // if an error occurred during linking, stop processing if (null == output) { return this.messageHandler.LastErrorNumber; } } else if (0 != sections.Count) { throw new InvalidOperationException(LightStrings.EXP_CannotLinkObjFilesWithOutpuFile); } // Now that the output object is either linked or loaded, tell the binder file manager about it. this.binder.FileManager.Output = output; // only output the xml if its a patch build or user specfied to only output wixout if (this.outputXml || OutputType.Patch == output.Type) { string outputExtension = Path.GetExtension(this.outputFile); if (null == outputExtension || 0 == outputExtension.Length || ".wix" == outputExtension) { if (OutputType.Patch == output.Type) { this.outputFile = Path.ChangeExtension(this.outputFile, ".wixmsp"); } else { this.outputFile = Path.ChangeExtension(this.outputFile, ".wixout"); } } output.Save(this.outputFile, (this.bindFiles ? this.binder.FileManager : null), this.wixVariableResolver, this.binder.TempFilesLocation); } else // finish creating the MSI/MSM { string outputExtension = Path.GetExtension(this.outputFile); if (null == outputExtension || 0 == outputExtension.Length || ".wix" == outputExtension) { outputExtension = Output.GetExtension(output.Type); this.outputFile = Path.ChangeExtension(this.outputFile, outputExtension); } this.binder.Bind(output, this.outputFile); } } catch (WixException we) { if (we is WixInvalidIdtException) { // make sure the IDT files stay around this.tidy = false; } this.messageHandler.Display(this, we.Error); } catch (Exception e) { // make sure the files stay around for debugging this.tidy = false; this.messageHandler.Display(this, WixErrors.UnexpectedException(e.Message, e.GetType().ToString(), e.StackTrace)); if (e is NullReferenceException || e is SEHException) { throw; } } finally { if (null != binder) { this.binder.Cleanup(this.tidy); } } return this.messageHandler.LastErrorNumber; }
/// <summary> /// Main running method for the application. /// </summary> /// <param name="args">Commandline arguments to the application.</param> /// <returns>Returns the application error code.</returns> private int Run(string[] args) { try { XmlSchemaCollection objectSchema = new XmlSchemaCollection(); FileInfo currentFile = null; ArrayList intermediates = new ArrayList(); Linker linker = null; Microsoft.Tools.WindowsInstallerXml.Binder binder = null; Localizer localizer = null; try { // parse the command line this.ParseCommandLine(args); // exit if there was an error parsing the command line (otherwise the logo appears after error messages) if (this.messageHandler.FoundError) { return this.messageHandler.PostProcess(); } if (0 == this.objectFiles.Count) { this.showHelp = true; } else if (null == this.outputFile) { if (1 < this.objectFiles.Count) { throw new ArgumentException("must specify output file when using more than one input file", "-out"); } FileInfo fi = (FileInfo)this.objectFiles[0]; this.outputFile = new FileInfo(Path.ChangeExtension(fi.Name, ".wix")); // we'll let the linker change the extension later } if (this.showLogo) { Assembly lightAssembly = Assembly.GetExecutingAssembly(); Console.WriteLine("Microsoft (R) Windows Installer Xml Linker version {0}", lightAssembly.GetName().Version.ToString()); Console.WriteLine("Copyright (C) Microsoft Corporation 2003. All rights reserved."); Console.WriteLine(); } if (this.showHelp) { Console.WriteLine(" usage: light.exe [-?] [-b basePath] [-nologo] [-out outputFile] objectFile [objectFile ...]"); Console.WriteLine(); Console.WriteLine(" -ai allow identical rows, identical rows will be treated as a warning"); Console.WriteLine(" -au (experimental) allow unresolved references, will not create a valid output"); Console.WriteLine(" -b base path to locate all files (default: current directory)"); Console.WriteLine(" -cc path to cache built cabinets (will not be deleted after linking)"); Console.WriteLine(" -ext extension (class, assembly), should extend SchemaExtension or BinderExtension"); Console.WriteLine(" -fv add a 'fileVersion' entry to the MsiAssemblyName table (rarely needed)"); Console.WriteLine(" -i specify the base output path for uncompressed images (default: -out parameter)"); Console.WriteLine(" -loc read localization string sfrom .wxl file"); Console.WriteLine(" -nologo skip printing light logo information"); Console.WriteLine(" -notidy do not delete temporary files (useful for debugging)"); Console.WriteLine(" -reusecab reuse cabinets from cabinet cache"); Console.WriteLine(" -out specify output file (default: write to current directory)"); Console.WriteLine(" -xo output xml instead of MSI format"); Console.WriteLine(" -pedantic:<level> pedantic checks (levels: easy, heroic, legendary)"); Console.WriteLine(" -reusecab reuse cabinets from cabinet cache"); Console.WriteLine(" -sa suppress assemblies: do not get assembly name information for assemblies"); Console.WriteLine(" -sacl suppress resetting ACLs (useful when laying out image to a network share)"); Console.WriteLine(" -sadmin suppress default admin sequence actions"); Console.WriteLine(" -sadv suppress default adv sequence actions"); Console.WriteLine(" -sa suppress assemblys: do not get assembly name information for assemblies"); Console.WriteLine(" -sf suppress files: do not get any file information (equivalent to -sa and -sh)"); Console.WriteLine(" -sh suppress file info: do not get hash, version, language, etc"); Console.WriteLine(" -sl suppress layout"); Console.WriteLine(" -ss suppress schema validation of documents (performance boost)"); Console.WriteLine(" -sui suppress default UI sequence actions"); Console.WriteLine(" -sv suppress intermediate file version mismatch checking"); Console.WriteLine(" -ts tag sectionId attribute on tuples (ignored if not used with -xo)"); Console.WriteLine(" -ust use small table definitions (for backwards compatiblity)"); Console.WriteLine(" -wx treat warnings as errors"); Console.WriteLine(" -w<N> set the warning level (0: show all, 3: show none)"); Console.WriteLine(" -sw suppress all warnings (same as -w3)"); Console.WriteLine(" -sw<N> suppress warning with specific message ID"); Console.WriteLine(" -v verbose output (same as -v2)"); Console.WriteLine(" -v<N> sets the level of verbose output (0: most output, 3: none)"); Console.WriteLine(" -? this help information"); Console.WriteLine(); Console.WriteLine("Environment variables:"); Console.WriteLine(" WIX_TEMP overrides the temporary directory used for cab creation, msm exploding, ..."); Console.WriteLine(); Console.WriteLine("Common extensions:"); Console.WriteLine(" .wxs - Windows installer Xml Source file"); Console.WriteLine(" .wxi - Windows installer Xml Include file"); Console.WriteLine(" .wxl - Windows installer Xml Localization file"); Console.WriteLine(" .wixobj - Windows installer Xml Object file (in XML format)"); Console.WriteLine(" .wixlib - Windows installer Xml Library file (in XML format)"); Console.WriteLine(" .wixout - Windows installer Xml Output file (in XML format)"); Console.WriteLine(); Console.WriteLine(" .msm - Windows installer Merge Module"); Console.WriteLine(" .msi - Windows installer Product Database"); Console.WriteLine(" .mst - Windows installer Transform"); Console.WriteLine(" .pcp - Windows installer Patch Creation Package"); Console.WriteLine(); Console.WriteLine("For more information see: http://wix.sourceforge.net"); return this.messageHandler.PostProcess(); } // create the linker and the binder linker = new Linker(this.useSmallTables); binder = new Microsoft.Tools.WindowsInstallerXml.Binder(this.useSmallTables); linker.AllowIdenticalRows = this.allowIdenticalRows; linker.AllowUnresolvedReferences = this.allowUnresolvedReferences; linker.PedanticLevel = this.pedanticLevel; // set the sequence suppression options linker.SuppressAdminSequence = this.suppressAdminSequence; linker.SuppressAdvertiseSequence = this.suppressAdvertiseSequence; linker.SuppressUISequence = this.suppressUISequence; linker.SectionIdOnTuples = this.sectionIdOnTuples; binder.SuppressAclReset = this.suppressAclReset; binder.SetMsiAssemblyNameFileVersion = this.setMsiAssemblyNameFileVersion; binder.SuppressAssemblies = this.suppressAssemblies; binder.SuppressFileHashAndInfo = this.suppressFileHashAndInfo; if (this.suppressFiles) { binder.SuppressAssemblies = true; binder.SuppressFileHashAndInfo = true; } binder.SuppressLayout = this.suppressLayout; binder.TempFilesLocation = Environment.GetEnvironmentVariable("WIX_TEMP"); if (null != this.cabCachePath || this.reuseCabinets) { // ensure the cabinet cache path exists if we are going to use it if (null != this.cabCachePath && !Directory.Exists(this.cabCachePath)) { Directory.CreateDirectory(this.cabCachePath); } } if (null != this.basePaths) { foreach (string basePath in this.basePaths) { this.sourcePaths.Add(basePath); } } // load any extensions bool binderExtensionLoaded = false; foreach (string extension in this.extensionList) { Type extensionType = Type.GetType(extension); if (null == extensionType) { throw new WixInvalidExtensionException(extension); } if (extensionType.IsSubclassOf(typeof(BinderExtension))) { object[] extensionArgs = new object[] { this.basePaths, this.cabCachePath, this.reuseCabinets, this.sourcePaths }; BinderExtension binderExtension = Activator.CreateInstance(extensionType, extensionArgs) as BinderExtension; Debug.Assert(null != binderExtension); if (binderExtensionLoaded) { throw new ArgumentException(String.Format(CultureInfo.InvariantCulture, "cannot load binder extension: {0}. light can only load one binder extension and has already loaded binder extension: {1}.", binderExtension.ToString(), binder.Extension.ToString()), "ext"); } binder.Extension = binderExtension; binderExtensionLoaded = true; } else if (extensionType.IsSubclassOf(typeof(SchemaExtension))) { linker.AddExtension((SchemaExtension)Activator.CreateInstance(extensionType)); } else { throw new WixInvalidExtensionException(extension, extensionType, typeof(BinderExtension), typeof(SchemaExtension)); } } // if the binder extension has not been loaded yet use the built-in binder extension if (!binderExtensionLoaded) { binder.Extension = new LightBinderExtension(this.basePaths, this.cabCachePath, this.reuseCabinets, this.sourcePaths); } if (null != this.imagebaseOutputPath) { binder.ImageBaseOutputPath = this.imagebaseOutputPath; } // set the message handlers linker.Message += new MessageEventHandler(this.messageHandler.Display); binder.Message += new MessageEventHandler(this.messageHandler.Display); // load the object schema if (!this.suppressSchema) { Assembly wixAssembly = Assembly.Load("wix"); using (Stream objectsSchemaStream = wixAssembly.GetManifestResourceStream("Microsoft.Tools.WindowsInstallerXml.Xsd.objects.xsd")) { XmlReader reader = new XmlTextReader(objectsSchemaStream); objectSchema.Add("http://schemas.microsoft.com/wix/2003/04/objects", reader); } } Output output = null; // loop through all the believed object files foreach (FileInfo objectFile in this.objectFiles) { currentFile = objectFile; string dirName = Path.GetDirectoryName(currentFile.FullName); if (!StringArrayContains(this.sourcePaths, dirName)) { this.sourcePaths.Add(dirName); } // load the object file into an intermediate object and add it to the list to be linked using (Stream fileStream = new FileStream(currentFile.FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { XmlReader fileReader = new XmlTextReader(fileStream); try { XmlReader intermediateReader = fileReader; if (!this.suppressSchema) { intermediateReader = new XmlValidatingReader(fileReader); ((XmlValidatingReader)intermediateReader).Schemas.Add(objectSchema); } Intermediate intermediate = Intermediate.Load(intermediateReader, currentFile.FullName, linker.TableDefinitions, this.suppressVersionCheck); intermediates.Add(intermediate); continue; // next file } catch (WixNotIntermediateException) { // try another format } try { Library library = Library.Load(currentFile.FullName, linker.TableDefinitions, this.suppressVersionCheck); intermediates.AddRange(library.Intermediates); continue; // next file } catch (WixNotLibraryException) { // try another format } output = Output.Load(currentFile.FullName, this.suppressVersionCheck); } } // instantiate the localizer and load any wixloc files if (0 < this.localizationFiles.Count || !this.outputXml) { localizer = new Localizer(); localizer.Message += new MessageEventHandler(this.messageHandler.Display); // load each wixloc file foreach (string localizationFile in this.localizationFiles) { localizer.LoadFromFile(localizationFile); } // immediately stop processing if any errors were found if (this.messageHandler.FoundError) { return this.messageHandler.PostProcess(); } } // and now for the fun part currentFile = this.outputFile; if (null == output) { // tell the linker about the localizer linker.Localizer = localizer; localizer = null; output = linker.Link((Intermediate[])intermediates.ToArray(typeof(Intermediate))); // if an error occurred during linking, stop processing if (null == output) { return this.messageHandler.PostProcess(); } } else if (0 != intermediates.Count) { throw new InvalidOperationException("Cannot link object files (.wixobj) files with an output file (.wixout)"); } output.Path = this.outputFile.FullName; // only output the xml if (this.outputXml) { string outputExtension = Path.GetExtension(this.outputFile.FullName); if (null == outputExtension || 0 == outputExtension.Length || ".wix" == outputExtension) { output.Path = Path.ChangeExtension(this.outputFile.FullName, ".wixout"); } output.Save(); } else // finish creating the MSI/MSM { string outputExtension = Path.GetExtension(this.outputFile.FullName); if (null == outputExtension || 0 == outputExtension.Length || ".wix" == outputExtension) { if (OutputType.Module == output.Type) { output.Path = Path.ChangeExtension(this.outputFile.FullName, ".msm"); } else if (OutputType.PatchCreation == output.Type) { output.Path = Path.ChangeExtension(this.outputFile.FullName, ".pcp"); } else { output.Path = Path.ChangeExtension(this.outputFile.FullName, ".msi"); } } // tell the binder about the localizer binder.Localizer = localizer; binder.Bind(output); } currentFile = null; } catch (WixInvalidIdtException) { this.tidy = false; // make sure the IDT files stay around throw; } catch (WixMergeFailureException) { this.tidy = false; // make sure the merge.log stays around throw; } finally { if (null != binder) { if (this.tidy) { if (!binder.DeleteTempFiles()) { Console.WriteLine("Warning, failed to delete temporary directory: {0}", binder.TempFilesLocation); } } else { Console.WriteLine("Temporary directory located at '{0}'.", binder.TempFilesLocation); } } } } catch (WixException we) { // TODO: once all WixExceptions are converted to errors, this clause // should be a no-op that just catches WixFatalErrorException's this.messageHandler.Display("light.exe", "LGHT", we); return 1; } catch (Exception e) { this.OnMessage(WixErrors.UnexpectedException(e.Message, e.GetType().ToString(), e.StackTrace)); if (e is NullReferenceException || e is SEHException) { throw; } } return this.messageHandler.PostProcess(); }
/// <summary> /// Main running method for the application. /// </summary> /// <param name="args">Commandline arguments to the application.</param> /// <returns>Returns the application error code.</returns> private int Run(string[] args) { Microsoft.Tools.WindowsInstallerXml.Binder binder = null; Linker linker = null; Localizer localizer = null; SectionCollection sections = new SectionCollection(); ArrayList transforms = new ArrayList(); try { // parse the command line this.ParseCommandLine(args); // exit if there was an error parsing the command line (otherwise the logo appears after error messages) if (this.messageHandler.EncounteredError) { return(this.messageHandler.LastErrorNumber); } if (0 == this.inputFiles.Count) { this.showHelp = true; } else if (null == this.outputFile) { if (1 < this.inputFiles.Count) { throw new ArgumentException("must specify output file when using more than one input file", "-out"); } this.outputFile = Path.ChangeExtension(Path.GetFileName(this.inputFiles[0]), ".wix"); // we'll let the linker change the extension later } if (this.showLogo) { Assembly lightAssembly = Assembly.GetExecutingAssembly(); Console.WriteLine("Microsoft (R) Windows Installer Xml Linker version {0}", lightAssembly.GetName().Version.ToString()); Console.WriteLine("Copyright (C) Microsoft Corporation 2003. All rights reserved."); Console.WriteLine(); } if (this.showHelp) { Console.WriteLine(" usage: light.exe [-?] [-b basePath] [-nologo] [-out outputFile] objectFile [objectFile ...]"); Console.WriteLine(); Console.WriteLine(" -ai allow identical rows, identical rows will be treated as a warning"); Console.WriteLine(" -au (experimental) allow unresolved references, will not create a valid output"); Console.WriteLine(" -b base path to locate all files (default: current directory)"); Console.WriteLine(" -bf bind files into a wixout (only valid with -xo option)"); Console.WriteLine(" -cc path to cache built cabinets (will not be deleted after linking)"); Console.WriteLine(" -ct <N> number of threads to use when creating cabinets (default: %NUMBER_OF_PROCESSORS%)"); Console.WriteLine(" -cultures:<cultures> semicolon-delimited list of localized string cultures to load from libraries"); Console.WriteLine(" -cub additional .cub file containing ICEs to run"); Console.WriteLine(" -d<name>=<value> define a wix variable"); Console.WriteLine(" -ext extension assembly or \"class, assembly\""); Console.WriteLine(" -fv add a 'fileVersion' entry to the MsiAssemblyName table (rarely needed)"); Console.WriteLine(" -loc <loc.wxl> read localization strings from .wxl file"); Console.WriteLine(" -nologo skip printing light logo information"); Console.WriteLine(" -notidy do not delete temporary files (useful for debugging)"); Console.WriteLine(" -out specify output file (default: write to current directory)"); Console.WriteLine(" -pedantic show pedantic messages"); Console.WriteLine(" -reusecab reuse cabinets from cabinet cache"); Console.WriteLine(" -sa suppress assemblies: do not get assembly name information for assemblies"); Console.WriteLine(" -sacl suppress resetting ACLs (useful when laying out image to a network share)"); Console.WriteLine(" -sadmin suppress default admin sequence actions"); Console.WriteLine(" -sadv suppress default adv sequence actions"); Console.WriteLine(" -sdut suppress dropping unreal tables to the output image (default with -xo)"); Console.WriteLine(" -sice:<ICE> suppress an internal consistency evaluator (ICE)"); Console.WriteLine(" -sma suppress processing the data in MsiAssembly table"); Console.WriteLine(" -sf suppress files: do not get any file information (equivalent to -sa and -sh)"); Console.WriteLine(" -sh suppress file info: do not get hash, version, language, etc"); Console.WriteLine(" -sl suppress layout"); Console.WriteLine(" -ss suppress schema validation of documents (performance boost)"); Console.WriteLine(" -sui suppress default UI sequence actions"); Console.WriteLine(" -sv suppress intermediate file version mismatch checking"); Console.WriteLine(" -sval suppress MSI/MSM validation"); Console.WriteLine(" -sw<N> suppress warning with specific message ID"); Console.WriteLine(" -ts tag sectionId attribute on rows (default with -xo)"); Console.WriteLine(" -tsa tag sectionId attribute on rows, generating when null (default with -xo)"); Console.WriteLine(" -usf <output.xml> unreferenced symbols file"); Console.WriteLine(" -v verbose output"); Console.WriteLine(" -wx treat warnings as errors"); Console.WriteLine(" -xo output xml instead of MSI format"); Console.WriteLine(" -? this help information"); Console.WriteLine(); Console.WriteLine("Environment variables:"); Console.WriteLine(" WIX_TEMP overrides the temporary directory used for cab creation, msm exploding, ..."); Console.WriteLine(); Console.WriteLine("Common extensions:"); Console.WriteLine(" .wxi - Windows installer Xml Include file"); Console.WriteLine(" .wxl - Windows installer Xml Localization file"); Console.WriteLine(" .wxs - Windows installer Xml Source file"); Console.WriteLine(" .wixlib - Windows installer Xml Library file (in XML format)"); Console.WriteLine(" .wixobj - Windows installer Xml Object file (in XML format)"); Console.WriteLine(" .wixout - Windows installer Xml Output file (in XML format)"); Console.WriteLine(); Console.WriteLine(" .msi - Windows installer Product Database"); Console.WriteLine(" .msm - Windows installer Merge Module"); Console.WriteLine(" .msp - Windows installer Patch"); Console.WriteLine(" .mst - Windows installer Transform"); Console.WriteLine(" .pcp - Windows installer Patch Creation Package"); Console.WriteLine(); Console.WriteLine("For more information see: http://wix.sourceforge.net"); return(this.messageHandler.LastErrorNumber); } // create the linker, binder, and validator linker = new Linker(); binder = new Microsoft.Tools.WindowsInstallerXml.Binder(); linker.AllowIdenticalRows = this.allowIdenticalRows; linker.AllowUnresolvedReferences = this.allowUnresolvedReferences; linker.Cultures = this.cultures; linker.UnreferencedSymbolsFile = this.unreferencedSymbolsFile; linker.ShowPedanticMessages = this.showPedanticMessages; linker.SuppressDroppingUnrealTables = this.suppressDroppingUnrealTables; linker.SuppressMsiAssemblyTable = this.suppressMsiAssemblyTable; linker.WixVariableResolver = this.wixVariableResolver; // set the sequence suppression options linker.SuppressAdminSequence = this.suppressAdminSequence; linker.SuppressAdvertiseSequence = this.suppressAdvertiseSequence; linker.SuppressUISequence = this.suppressUISequence; linker.SectionIdOnRows = this.sectionIdOnRows; linker.GenerateSectionIds = this.generateSectionIds; // default the number of cabbing threads to the number of processors if it wasn't specified if (0 == this.cabbingThreadCount) { string numberOfProcessors = System.Environment.GetEnvironmentVariable("NUMBER_OF_PROCESSORS"); try { if (null != numberOfProcessors) { this.cabbingThreadCount = Convert.ToInt32(numberOfProcessors, CultureInfo.InvariantCulture.NumberFormat); if (0 >= this.cabbingThreadCount) { throw new WixException(WixErrors.IllegalEnvironmentVariable("NUMBER_OF_PROCESSORS", numberOfProcessors)); } } else // default to 1 if the environment variable is not set { this.cabbingThreadCount = 1; } } catch (ArgumentException) { throw new WixException(WixErrors.IllegalEnvironmentVariable("NUMBER_OF_PROCESSORS", numberOfProcessors)); } catch (FormatException) { throw new WixException(WixErrors.IllegalEnvironmentVariable("NUMBER_OF_PROCESSORS", numberOfProcessors)); } } binder.CabbingThreadCount = this.cabbingThreadCount; binder.SuppressAclReset = this.suppressAclReset; binder.SetMsiAssemblyNameFileVersion = this.setMsiAssemblyNameFileVersion; binder.SuppressAssemblies = this.suppressAssemblies; binder.SuppressFileHashAndInfo = this.suppressFileHashAndInfo; if (this.suppressFiles) { binder.SuppressAssemblies = true; binder.SuppressFileHashAndInfo = true; } binder.SuppressLayout = this.suppressLayout; binder.TempFilesLocation = Environment.GetEnvironmentVariable("WIX_TEMP"); binder.WixVariableResolver = this.wixVariableResolver; validator.TempFilesLocation = Environment.GetEnvironmentVariable("WIX_TEMP"); if (null != this.cabCachePath || this.reuseCabinets) { // ensure the cabinet cache path exists if we are going to use it if (null != this.cabCachePath && !Directory.Exists(this.cabCachePath)) { Directory.CreateDirectory(this.cabCachePath); } } if (null != this.basePaths) { foreach (string basePath in this.basePaths) { this.sourcePaths.Add(basePath); } } // load any extensions bool binderExtensionLoaded = false; bool validatorExtensionLoaded = false; foreach (string extension in this.extensionList) { WixExtension wixExtension = WixExtension.Load(extension); linker.AddExtension(wixExtension); if (null != wixExtension.BinderExtension) { if (binderExtensionLoaded) { throw new ArgumentException(String.Format(CultureInfo.InvariantCulture, "cannot load binder extension: {0}. light can only load one binder extension and has already loaded binder extension: {1}.", wixExtension.BinderExtension.GetType().ToString(), binder.Extension.ToString()), "ext"); } binder.Extension = wixExtension.BinderExtension; binderExtensionLoaded = true; } ValidatorExtension validatorExtension = wixExtension.ValidatorExtension; if (null != validatorExtension) { if (validatorExtensionLoaded) { throw new ArgumentException(String.Format(CultureInfo.InvariantCulture, "cannot load linker extension: {0}. light can only load one link extension and has already loaded link extension: {1}.", validatorExtension.GetType().ToString(), validator.Extension.ToString()), "ext"); } validator.Extension = validatorExtension; validatorExtensionLoaded = true; } } // set the message handlers linker.Message += new MessageEventHandler(this.messageHandler.Display); binder.Message += new MessageEventHandler(this.messageHandler.Display); validator.Extension.Message += new MessageEventHandler(this.messageHandler.Display); Output output = null; // instantiate the localizer and load any localization files if (0 < this.localizationFiles.Count || null != this.cultures || !this.outputXml) { localizer = new Localizer(); localizer.Message += new MessageEventHandler(this.messageHandler.Display); // load each localization file foreach (string localizationFile in this.localizationFiles) { Localization localization = Localization.Load(localizationFile, linker.TableDefinitions, this.suppressSchema); localizer.AddLocalization(localization); } // immediately stop processing if any errors were found if (this.messageHandler.EncounteredError) { return(this.messageHandler.LastErrorNumber); } } // loop through all the believed object files foreach (string inputFile in this.inputFiles) { string dirName = Path.GetDirectoryName(inputFile); string inputFileFullPath = Path.GetFullPath(inputFile); if (!this.sourcePaths.Contains(dirName)) { this.sourcePaths.Add(dirName); } // try loading as an object file try { Intermediate intermediate = Intermediate.Load(inputFileFullPath, linker.TableDefinitions, this.suppressVersionCheck, this.suppressSchema); sections.AddRange(intermediate.Sections); continue; // next file } catch (WixNotIntermediateException) { // try another format } // try loading as a library file try { Library library = Library.Load(inputFileFullPath, linker.TableDefinitions, this.suppressVersionCheck, this.suppressSchema); sections.AddRange(library.Sections); // load the localization files for the selected cultures if (null != this.cultures) { Localization localization = library.GetLocalization(this.cultures); if (null != localization) { localizer.AddLocalization(localization); } } continue; // next file } catch (WixNotLibraryException) { // try another format } // try loading as an output file output = Output.Load(inputFileFullPath, this.suppressVersionCheck, this.suppressSchema); } // immediately stop processing if any errors were found if (this.messageHandler.EncounteredError) { return(this.messageHandler.LastErrorNumber); } // set the binder extension information foreach (string basePath in this.basePaths) { binder.Extension.BasePaths.Add(basePath); } binder.Extension.CabCachePath = this.cabCachePath; binder.Extension.ReuseCabinets = this.reuseCabinets; foreach (string sourcePath in this.sourcePaths) { binder.Extension.SourcePaths.Add(sourcePath); } // and now for the fun part if (null == output) { // tell the linker about the localizer linker.Localizer = localizer; localizer = null; output = linker.Link(sections, transforms); // if an error occurred during linking, stop processing if (null == output) { return(this.messageHandler.LastErrorNumber); } } else if (0 != sections.Count) { throw new InvalidOperationException("Cannot link object files (.wixobj) files with an output file (.wixout)"); } // Now that the output object is either linked or loaded, tell the binder extension about it. binder.Extension.Output = output; // only output the xml if its a patch build or user specfied to only output wixout if (this.outputXml || OutputType.Patch == output.Type) { string outputExtension = Path.GetExtension(this.outputFile); if (null == outputExtension || 0 == outputExtension.Length || ".wix" == outputExtension) { if (OutputType.Patch == output.Type) { this.outputFile = Path.ChangeExtension(this.outputFile, ".wixmsp"); } else { this.outputFile = Path.ChangeExtension(this.outputFile, ".wixout"); } } output.Save(this.outputFile, (this.bindFiles ? binder.Extension : null), this.wixVariableResolver, binder.TempFilesLocation); } else // finish creating the MSI/MSM { string outputExtension = Path.GetExtension(this.outputFile); if (null == outputExtension || 0 == outputExtension.Length || ".wix" == outputExtension) { if (OutputType.Module == output.Type) { this.outputFile = Path.ChangeExtension(this.outputFile, ".msm"); } else if (OutputType.PatchCreation == output.Type) { this.outputFile = Path.ChangeExtension(this.outputFile, ".pcp"); } else { this.outputFile = Path.ChangeExtension(this.outputFile, ".msi"); } } // tell the binder about the localizer binder.Localizer = localizer; // tell the binder about the validator if validation isn't suppressed if (!this.suppressValidation && (OutputType.Module == output.Type || OutputType.Product == output.Type)) { // set the default cube file Assembly lightAssembly = Assembly.GetExecutingAssembly(); string lightDirectory = Path.GetDirectoryName(lightAssembly.Location); if (OutputType.Module == output.Type) { validator.AddCubeFile(Path.Combine(lightDirectory, "mergemod.cub")); } else // product { validator.AddCubeFile(Path.Combine(lightDirectory, "darice.cub")); } // disable ICE33 by default this.suppressICEs.Add("ICE33"); // set the suppressed ICEs string[] suppressICEArray = new string[this.suppressICEs.Count]; this.suppressICEs.CopyTo(suppressICEArray, 0); validator.SuppressedICEs = suppressICEArray; binder.Validator = validator; } binder.Bind(output, this.outputFile); } } catch (WixException we) { if (we is WixInvalidIdtException) { // make sure the IDT files stay around this.tidy = false; } this.messageHandler.Display(this, we.Error); } catch (Exception e) { // make sure the files stay around for debugging this.tidy = false; this.messageHandler.Display(this, WixErrors.UnexpectedException(e.Message, e.GetType().ToString(), e.StackTrace)); if (e is NullReferenceException || e is SEHException) { throw; } } finally { if (null != binder) { if (this.tidy) { if (!binder.DeleteTempFiles()) { Console.WriteLine("Warning, failed to delete temporary directory: {0}", binder.TempFilesLocation); } } else { Console.WriteLine("Binder temporary directory located at '{0}'.", binder.TempFilesLocation); } } if (null != validator) { if (this.tidy) { if (!validator.DeleteTempFiles()) { Console.WriteLine("Warning, failed to delete temporary directory: {0}", validator.TempFilesLocation); } } else { Console.WriteLine("Validator temporary directory located at '{0}'.", validator.TempFilesLocation); } } } return(this.messageHandler.LastErrorNumber); }