/// <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 { Librarian librarian = null; SectionCollection sections = new SectionCollection(); // 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"); } // we'll let the linker change the extension later this.outputFile = Path.ChangeExtension(this.inputFiles[0], ".wix"); } if (this.showLogo) { Assembly litAssembly = Assembly.GetExecutingAssembly(); Console.WriteLine("Microsoft (R) Windows Installer Xml Library Tool version {0}", litAssembly.GetName().Version.ToString()); Console.WriteLine("Copyright (C) Microsoft Corporation 2003. All rights reserved."); Console.WriteLine(); } if (this.showHelp) { Console.WriteLine(" usage: lit.exe [-?] [-nologo] [-out libraryFile] objectFile [objectFile ...]"); Console.WriteLine(); Console.WriteLine(" -nologo skip printing lit logo information"); Console.WriteLine(" -out specify output file (default: write to current directory)"); Console.WriteLine(); Console.WriteLine(" -b base path to locate all files (default: current directory)"); Console.WriteLine(" -bf bind files into the library file"); Console.WriteLine(" -ext extension assembly or \"class, assembly\""); Console.WriteLine(" -loc <loc.wxl> bind localization strings from a wxl into the library file"); Console.WriteLine(" -ss suppress schema validation of documents (performance boost)"); Console.WriteLine(" -sv suppress intermediate file version mismatch checking"); Console.WriteLine(" -sw<N> suppress warning with specific message ID"); Console.WriteLine(" -wx treat warnings as errors"); Console.WriteLine(" -v verbose output"); Console.WriteLine(" -? this help information"); Console.WriteLine(); Console.WriteLine("Common extensions:"); Console.WriteLine(" .wxs - Windows installer Xml Source file"); Console.WriteLine(" .wxi - Windows installer Xml Include 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(" .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 librarian librarian = new Librarian(); librarian.Message += new MessageEventHandler(this.messageHandler.Display); if (null != this.basePaths) { foreach (string basePath in this.basePaths) { this.sourcePaths.Add(basePath); } } // load any extensions foreach (string extension in this.extensionList) { WixExtension wixExtension = WixExtension.Load(extension); librarian.AddExtension(wixExtension); // load the binder extension regardless of whether it will be used in case there is a collision if (null != wixExtension.BinderExtension) { if (null != this.binderExtension) { throw new ArgumentException(String.Format(CultureInfo.InvariantCulture, "cannot load binder extension: {0}. lit can only load one binder extension and has already loaded binder extension: {1}.", wixExtension.BinderExtension.GetType().ToString(), this.binderExtension.GetType().ToString()), "ext"); } this.binderExtension = wixExtension.BinderExtension; } } // add the sections to the librarian foreach (string inputFile in this.inputFiles) { string inputFileFullPath = Path.GetFullPath(inputFile); string dirName = Path.GetDirectoryName(inputFileFullPath); if (!this.sourcePaths.Contains(dirName)) { this.sourcePaths.Add(dirName); } // try loading as an object file try { Intermediate intermediate = Intermediate.Load(inputFileFullPath, librarian.TableDefinitions, this.suppressVersionCheck, this.suppressSchema); sections.AddRange(intermediate.Sections); continue; // next file } catch (WixNotIntermediateException) { // try another format } // try loading as a library file Library loadedLibrary = Library.Load(inputFileFullPath, librarian.TableDefinitions, this.suppressVersionCheck, this.suppressSchema); sections.AddRange(loadedLibrary.Sections); } // and now for the fun part Library library = librarian.Combine(sections); // save the library output if an error did not occur if (null != library) { if (this.bindFiles) { // if the binder extension has not been loaded yet use the built-in binder extension if (null == this.binderExtension) { this.binderExtension = new BinderExtension(); } // set the binder extension information foreach (string basePath in this.basePaths) { this.binderExtension.BasePaths.Add(basePath); } foreach (string sourcePath in this.sourcePaths) { this.binderExtension.SourcePaths.Add(sourcePath); } } else { this.binderExtension = null; } foreach (string localizationFile in this.localizationFiles) { Localization localization = Localization.Load(localizationFile, librarian.TableDefinitions, this.suppressSchema); library.AddLocalization(localization); } WixVariableResolver wixVariableResolver = new WixVariableResolver(); wixVariableResolver.Message += new MessageEventHandler(this.messageHandler.Display); library.Save(this.outputFile, this.binderExtension, wixVariableResolver); } } catch (WixException we) { this.messageHandler.Display(this, we.Error); } catch (Exception e) { this.messageHandler.Display(this, WixErrors.UnexpectedException(e.Message, e.GetType().ToString(), e.StackTrace)); if (e is NullReferenceException || e is SEHException) { throw; } } 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()); }