public void CanUpdateIntermediate() { var sln = new SourceLineNumber("test.wxs", 1); var section = new IntermediateSection("test", SectionType.Product, 65001); section.Symbols.Add(new ComponentSymbol(sln, new Identifier(AccessModifier.Public, "TestComponent")) { ComponentId = new Guid(1, 0, 0, new byte[8]).ToString("B"), DirectoryRef = "TestFolder", Location = ComponentLocation.Either, }); var intermediate = new Intermediate("TestIntermediate", IntermediateLevels.Compiled, new[] { section }, null); var path = Path.GetTempFileName(); try { intermediate.Save(path); var uri = new Uri(Path.GetFullPath(path)); var stream = File.Open(path, FileMode.Open, FileAccess.ReadWrite); using (var wixout = WixOutput.Read(uri, stream)) { var loaded = Intermediate.Load(wixout); var symbol = (ComponentSymbol)loaded.Sections.Single().Symbols.Single(); Assert.Equal("TestComponent", symbol.Id.Id); Assert.Equal(AccessModifier.Public, symbol.Id.Access); wixout.Reopen(writable: true); section.Symbols.Add(new ComponentSymbol(sln, new Identifier(AccessModifier.Public, "NewComponent")) { ComponentId = new Guid(1, 0, 0, new byte[8]).ToString("B"), }); intermediate.Save(wixout); loaded = Intermediate.Load(wixout); var newSymbol = loaded.Sections.Single().Symbols.Where(t => t.Id.Id == "NewComponent"); Assert.Single(newSymbol); } var loadedAfterDispose = Intermediate.Load(path); var newSymbolStillThere = loadedAfterDispose.Sections.Single().Symbols.Where(t => t.Id.Id == "NewComponent"); Assert.Single(newSymbolStillThere); } finally { File.Delete(path); } }
public void CanSaveAndLoadIntermediate() { var sln = new SourceLineNumber("test.wxs", 1); var section = new IntermediateSection("test", SectionType.Product, 65001); section.Tuples.Add(new ComponentTuple(sln, new Identifier("TestComponent", AccessModifier.Public)) { ComponentId = new Guid(1, 0, 0, new byte[8]).ToString("B"), Directory_ = "TestFolder", Attributes = 2, }); var intermediate = new Intermediate("TestIntermediate", new[] { section }, null, null); var path = Path.GetTempFileName(); intermediate.Save(path); var loaded = Intermediate.Load(path); var tuple = (ComponentTuple)loaded.Sections.Single().Tuples.Single(); Assert.Equal("TestComponent", tuple.Id.Id); Assert.Equal(AccessModifier.Public, tuple.Id.Access); Assert.Equal("TestFolder", tuple.Directory_); Assert.Equal(2, tuple.Attributes); }
private WixOutput CreateWixout(List <ITrackedFile> trackedFiles, Intermediate intermediate, string manifestPath, string baDataPath, string bextDataPath) { WixOutput wixout; if (String.IsNullOrEmpty(this.OutputPdbPath)) { wixout = WixOutput.Create(); } else { var trackPdb = this.BackendHelper.TrackFile(this.OutputPdbPath, TrackedFileType.Final); trackedFiles.Add(trackPdb); wixout = WixOutput.Create(trackPdb.Path); } intermediate.Save(wixout); wixout.ImportDataStream(BurnConstants.BurnManifestWixOutputStreamName, manifestPath); wixout.ImportDataStream(BurnConstants.BootstrapperApplicationDataWixOutputStreamName, baDataPath); wixout.ImportDataStream(BurnConstants.BundleExtensionDataWixOutputStreamName, bextDataPath); wixout.Reopen(); return(wixout); }
private void Compile(Compiler compiler, string name, Wix wix) { // Load the wix document into an XML document. XmlDocument xmlDocument = new XmlDocument(); using (MemoryStream writerStream = new MemoryStream()) { using (XmlTextWriter xmlWriter = new XmlTextWriter(writerStream, Encoding.Unicode)) { wix.OutputXml(xmlWriter); } using (MemoryStream readerStream = new MemoryStream(writerStream.GetBuffer())) { xmlDocument.Load(readerStream); } } // Compile it. Intermediate intermediate = compiler.Compile(xmlDocument); // Save the intermediate. string path = Path.Combine(m_buildFolder, name + File.Wixobj.Extension); intermediate.Save(path); }
public void CanSaveAndLoadIntermediateWithLocalization() { var sln = new SourceLineNumber("test.wxs", 10); var bindVariables = new[] { new BindVariable { Id = "TestVar1", Value = "TestValue1", SourceLineNumbers = sln }, new BindVariable { Id = "TestVar2", Value = "TestValue2", Overridable = true, SourceLineNumbers = sln }, }; var controls = new[] { new LocalizedControl("TestDlg1", "TestControl1", 10, 10, 100, 100, false, false, false, null), new LocalizedControl("TestDlg1", "TestControl2", 100, 90, 50, 70, false, false, false, "localized"), }; var localizations = new[] { new Localization(65001, null, bindVariables.ToDictionary(b => b.Id), controls.ToDictionary(c => c.GetKey())) }; var section = new IntermediateSection("test", SectionType.Product, 65001); section.Symbols.Add(new ComponentSymbol(sln, new Identifier(AccessModifier.Public, "TestComponent")) { ComponentId = new Guid(1, 0, 0, new byte[8]).ToString("B"), DirectoryRef = "TestFolder", Location = ComponentLocation.Either, }); var intermediate = new Intermediate("TestIntermediate", new[] { section }, localizations.ToDictionary(l => l.Culture)); var path = Path.GetTempFileName(); try { intermediate.Save(path); var loaded = Intermediate.Load(path); var loc = loaded.Localizations.Single(); Assert.Equal(65001, loc.Codepage); Assert.Empty(loc.Culture); Assert.Equal(new[] { "TestVar1/TestValue1/False", "TestVar2/TestValue2/True", }, loc.Variables.Select(v => String.Join("/", v.Id, v.Value, v.Overridable)).ToArray()); } finally { File.Delete(path); } }
public void CanSaveAndLoadIntermediateWithCustomDefinitions() { var sln = new SourceLineNumber("test.wxs", 1); var section = new IntermediateSection("test", SectionType.Product, 65001); var fieldDefs = new[] { new IntermediateFieldDefinition("A", IntermediateFieldType.String), new IntermediateFieldDefinition("B", IntermediateFieldType.Number), new IntermediateFieldDefinition("C", IntermediateFieldType.Bool), }; var symbolDef = new IntermediateSymbolDefinition("CustomDef2", fieldDefs, null); var symbol = symbolDef.CreateSymbol(sln, new Identifier(AccessModifier.Public, "customT")); symbol.Set(0, "foo"); symbol.Set(1, 2); symbol.Set(2, true); section.Symbols.Add(symbol); var intermediate = new Intermediate("TestIntermediate", new[] { section }, null); var path = Path.GetTempFileName(); try { intermediate.Save(path); var loaded = Intermediate.Load(path); var loadedSection = loaded.Sections.Single(); var loadedSymbol = loadedSection.Symbols.Single(); Assert.Equal("foo", loadedSymbol.AsString(0)); Assert.Equal(2, loadedSymbol[1].AsNumber()); Assert.True(loadedSymbol[2].AsBool()); } finally { File.Delete(path); } }
public void CanSaveAndLoadIntermediate() { var sln = new SourceLineNumber("test.wxs", 1); var section = new IntermediateSection("test", SectionType.Product, 65001); section.Symbols.Add(new ComponentSymbol(sln, new Identifier(AccessModifier.Public, "TestComponent")) { ComponentId = new Guid(1, 0, 0, new byte[8]).ToString("B"), DirectoryRef = "TestFolder", Location = ComponentLocation.Either, }); var intermediate = new Intermediate("TestIntermediate", IntermediateLevels.Compiled, new[] { section }, null); intermediate.UpdateLevel(IntermediateLevels.Linked); intermediate.UpdateLevel(IntermediateLevels.Resolved); var path = Path.GetTempFileName(); try { intermediate.Save(path); var loaded = Intermediate.Load(path); Assert.True(loaded.HasLevel(IntermediateLevels.Compiled)); Assert.True(loaded.HasLevel(IntermediateLevels.Linked)); Assert.True(loaded.HasLevel(IntermediateLevels.Resolved)); var symbol = (ComponentSymbol)loaded.Sections.Single().Symbols.Single(); Assert.Equal("TestComponent", symbol.Id.Id); Assert.Equal(AccessModifier.Public, symbol.Id.Access); Assert.Equal("TestFolder", symbol.DirectoryRef); Assert.Equal(ComponentLocation.Either, symbol.Location); } finally { File.Delete(path); } }
private WixOutput CreateWixout(List <ITrackedFile> trackedFiles, Intermediate intermediate, WindowsInstallerData output) { WixOutput wixout; if (String.IsNullOrEmpty(this.OutputPdbPath)) { wixout = WixOutput.Create(); } else { var trackPdb = this.BackendHelper.TrackFile(this.OutputPdbPath, TrackedFileType.Final); trackedFiles.Add(trackPdb); wixout = WixOutput.Create(trackPdb.Path); } intermediate.Save(wixout); output.Save(wixout); wixout.Reopen(); return(wixout); }
/// <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 { FileInfo currentFile = null; // 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.sourceFiles.Count) { this.showHelp = true; } else if (1 < this.sourceFiles.Count && null != this.outputFile) { throw new ArgumentException("cannot specify more than one source file with single output file. Either specify an output directory for the -out argument by ending the argument with a '\\' or remove the -out argument to have the source files compiled to the current directory.", "-out"); } if (this.showLogo) { Assembly candleAssembly = Assembly.GetExecutingAssembly(); Console.WriteLine("Microsoft (R) Windows Installer Xml Compiler version {0}", candleAssembly.GetName().Version.ToString()); Console.WriteLine("Copyright (C) Microsoft Corporation 2003. All rights reserved."); Console.WriteLine(); } if (this.showHelp) { Console.WriteLine(" usage: candle.exe [-?] [-nologo] [-out outputFile] sourceFile [sourceFile ...]"); Console.WriteLine(); Console.WriteLine(" -d<name>=<value> define a parameter for the preprocessor"); Console.WriteLine(" -p<file> preprocess to a file (or stdout if no file supplied)"); Console.WriteLine(" -I<dir> add to include search path"); Console.WriteLine(" -nologo skip printing candle logo information"); Console.WriteLine(" -out specify output file (default: write to current directory)"); Console.WriteLine(" -pedantic:<level> pedantic checks (levels: easy, heroic, legendary)"); Console.WriteLine(" -ss suppress schema validation of documents (performance boost)"); Console.WriteLine(" -ust use small table definitions (for backwards compatiblity)"); Console.WriteLine(" -trace show source trace for errors, warnings, and verbose messages"); Console.WriteLine(" -ext extension (class, assembly), should extend CompilerExtension"); Console.WriteLine(" -zs only do validation of documents (no output)"); 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("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 preprocessor and compiler Preprocessor preprocessor = new Preprocessor(); preprocessor.Message += new MessageEventHandler(this.messageHandler.Display); for (int i = 0; i < this.includeSearchPaths.Count; ++i) { preprocessor.IncludeSearchPaths.Add(this.includeSearchPaths[i]); } Compiler compiler = new Compiler(this.useSmallTables); compiler.Message += new MessageEventHandler(this.messageHandler.Display); compiler.PedanticLevel = this.pedanticLevel; compiler.SuppressValidate = this.suppressSchema; // load any extensions foreach (string extension in this.extensionList) { Type extensionType = Type.GetType(extension); if (null == extensionType) { throw new WixInvalidExtensionException(extension); } if (extensionType.IsSubclassOf(typeof(PreprocessorExtension))) { preprocessor.AddExtension((PreprocessorExtension)Activator.CreateInstance(extensionType)); } if (extensionType.IsSubclassOf(typeof(CompilerExtension))) { CompilerExtension compilerExtensionObject = Activator.CreateInstance(extensionType) as CompilerExtension; compiler.AddExtension(compilerExtensionObject); } if (!extensionType.IsSubclassOf(typeof(PreprocessorExtension)) && !extensionType.IsSubclassOf(typeof(CompilerExtension))) { throw new WixInvalidExtensionException(extension); } } // preprocess then compile each source file foreach (FileInfo sourceFile in this.sourceFiles) { currentFile = sourceFile; // point at the file we're working on in case a exception is thrown FileInfo targetFile; if (null != this.outputFile) { targetFile = this.outputFile; } else if (null != this.outputDirectory) { targetFile = new FileInfo(String.Concat(this.outputDirectory.FullName, Path.ChangeExtension(currentFile.Name, ".wixobj"))); } else { targetFile = new FileInfo(Path.ChangeExtension(currentFile.Name, ".wixobj")); } // print friendly message saying what file is being compiled Console.WriteLine(currentFile.Name); // need to clear and re-add the commandline defines for each file preprocessor.ResetParameters(); foreach (string param in this.parameters.Keys) { string name = param; if (!name.StartsWith("var.")) { name = String.Concat("var.", name); } preprocessor.Parameters.Add(name, (string)this.parameters[param]); } // preprocess the source XmlDocument sourceDocument; try { if (this.preprocessToStdout) { preprocessor.PreprocessOut = Console.Out; } else if (null != this.preprocessFile) { preprocessor.PreprocessOut = new StreamWriter(this.preprocessFile); } sourceDocument = preprocessor.Process(currentFile.FullName); } finally { if (null != preprocessor.PreprocessOut && Console.Out != preprocessor.PreprocessOut) { preprocessor.PreprocessOut.Close(); } } // if we're not actually going to compile anything, move on to the next file if (this.schemaOnly || null == sourceDocument || this.preprocessToStdout || null != this.preprocessFile) { continue; } // and now we do what we came here to do... Intermediate intermediate = compiler.Compile(sourceDocument, currentFile.FullName); // save the intermediate to disk if no errors were found for this source file if (null != intermediate) { intermediate.Save(targetFile.FullName); } // this file is was successful so clear the reference in case an exception gets thrown currentFile = null; } } 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("candle.exe", "CNDL", 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) { 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 (!this.fipsCompliant) { try { System.Security.Cryptography.MD5.Create(); } catch (TargetInvocationException) { this.messageHandler.Display(this, WixErrors.UseFipsArgument()); return(this.messageHandler.LastErrorNumber); } } if (0 == this.sourceFiles.Count) { this.showHelp = true; } else if (1 < this.sourceFiles.Count && null != this.outputFile) { throw new ArgumentException(CandleStrings.CannotSpecifyMoreThanOneSourceFileForSingleTargetFile, "-out"); } if (this.showLogo) { AppCommon.DisplayToolHeader(); } if (this.showHelp) { Console.WriteLine(CandleStrings.HelpMessage); AppCommon.DisplayToolFooter(); return(this.messageHandler.LastErrorNumber); } foreach (string parameter in this.invalidArgs) { this.messageHandler.Display(this, WixWarnings.UnsupportedCommandLineArgument(parameter)); } this.invalidArgs = null; // create the preprocessor and compiler Preprocessor preprocessor = new Preprocessor(); preprocessor.Message += new MessageEventHandler(this.messageHandler.Display); for (int i = 0; i < this.includeSearchPaths.Count; ++i) { preprocessor.IncludeSearchPaths.Add(this.includeSearchPaths[i]); } preprocessor.CurrentPlatform = this.platform; Compiler compiler = new Compiler(); compiler.Message += new MessageEventHandler(this.messageHandler.Display); compiler.SuppressFilesVitalByDefault = this.suppressFilesVitalByDefault; compiler.ShowPedanticMessages = this.showPedanticMessages; compiler.SuppressValidate = this.suppressSchema; compiler.CurrentPlatform = this.platform; compiler.FipsCompliant = this.fipsCompliant; // load any extensions foreach (string extension in this.extensionList) { WixExtension wixExtension = WixExtension.Load(extension); preprocessor.AddExtension(wixExtension); compiler.AddExtension(wixExtension); } // preprocess then compile each source file Dictionary <string, List <string> > sourcesForOutput = new Dictionary <string, List <string> >(StringComparer.OrdinalIgnoreCase); foreach (string sourceFileOrig in this.sourceFiles) { string sourceFile = sourceFileOrig; string targetFile = null; if (this.allowPerSourceOutputSpecification) { string[] parts = sourceFileOrig.Split(Candle.sourceOutputSeparator, 2); if (2 == parts.Length) { sourceFile = parts[0]; targetFile = parts[1]; } } string sourceFilePath = Path.GetFullPath(sourceFile); string sourceFileName = Path.GetFileName(sourceFile); if (null == targetFile) { if (null != this.outputFile) { targetFile = this.outputFile; } else if (null != this.outputDirectory) { targetFile = Path.Combine(this.outputDirectory, Path.ChangeExtension(sourceFileName, ".wixobj")); } else { targetFile = Path.ChangeExtension(sourceFileName, ".wixobj"); } } else if (!Path.IsPathRooted(targetFile) && null != this.outputDirectory) { targetFile = Path.Combine(this.outputDirectory, targetFile); } // print friendly message saying what file is being compiled Console.WriteLine(sourceFileName); // preprocess the source XmlDocument sourceDocument; try { if (this.preprocessToStdout) { preprocessor.PreprocessOut = Console.Out; } else if (null != this.preprocessFile) { preprocessor.PreprocessOut = new StreamWriter(this.preprocessFile); } sourceDocument = preprocessor.Process(sourceFilePath, this.parameters); } finally { if (null != preprocessor.PreprocessOut && Console.Out != preprocessor.PreprocessOut) { preprocessor.PreprocessOut.Close(); } } // if we're not actually going to compile anything, move on to the next file if (null == sourceDocument || this.preprocessToStdout || null != this.preprocessFile) { continue; } // and now we do what we came here to do... Intermediate intermediate = compiler.Compile(sourceDocument); // save the intermediate to disk if no errors were found for this source file if (null != intermediate) { intermediate.Save(targetFile); } // Track which source files result in a given output file, to ensure we aren't // overwriting the output. List <string> sources = null; string targetPath = Path.GetFullPath(targetFile); if (!sourcesForOutput.TryGetValue(targetPath, out sources)) { sources = new List <string>(); sourcesForOutput.Add(targetPath, sources); } sources.Add(sourceFile); } // Show an error for every output file that had more than 1 source file. foreach (KeyValuePair <string, List <string> > outputSources in sourcesForOutput) { if (1 < outputSources.Value.Count) { string sourceFiles = CompilerCore.CreateValueList(ValueListKind.None, outputSources.Value); this.messageHandler.Display(this, WixErrors.DuplicateSourcesForOutput(sourceFiles, outputSources.Key)); } } } 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); }
public void CanSaveAndLoadMultipleIntermediateWithCustomDefinitionsAndTags() { var sln = new SourceLineNumber("test.wxs", 1); // Intermediate #1 var fieldDefs = new[] { new IntermediateFieldDefinition("A", IntermediateFieldType.String), new IntermediateFieldDefinition("B", IntermediateFieldType.Number), new IntermediateFieldDefinition("C", IntermediateFieldType.Bool), }; var symbolDef = new IntermediateSymbolDefinition("CustomDef", fieldDefs, null); symbolDef.AddTag("customDef"); var symbol = symbolDef.CreateSymbol(sln, new Identifier(AccessModifier.Public, "customT")); symbol.Set(0, "foo"); symbol.Set(1, 2); symbol.Set(2, true); symbol.AddTag("symbol1tag"); var section = new IntermediateSection("test", SectionType.Product, 65001); section.Symbols.Add(symbol); var intermediate1 = new Intermediate("TestIntermediate", new[] { section }, null); // Intermediate #2 var fieldDefs2 = new[] { new IntermediateFieldDefinition("A", IntermediateFieldType.String), new IntermediateFieldDefinition("B", IntermediateFieldType.Number), new IntermediateFieldDefinition("C", IntermediateFieldType.Bool), new IntermediateFieldDefinition("D", IntermediateFieldType.String), }; var symbolDef2 = new IntermediateSymbolDefinition("CustomDef2", 1, fieldDefs2, null); symbolDef2.AddTag("customDef2"); symbolDef2.AddTag("customDef2 tag2"); var symbol2 = symbolDef2.CreateSymbol(sln, new Identifier(AccessModifier.Public, "customT2")); symbol2.Set(0, "bar"); symbol2.Set(1, 3); symbol2.Set(2, false); symbol2.Set(3, "baz"); symbol2.AddTag("symbol2tag1"); symbol2.AddTag("symbol2tag2"); var section2 = new IntermediateSection("test2", SectionType.Fragment, 65001); section2.Symbols.Add(symbol2); var intermediate2 = new Intermediate("TestIntermediate2", new[] { section2 }, null); // Save var path1 = Path.GetTempFileName(); var path2 = Path.GetTempFileName(); try { intermediate1.Save(path1); intermediate2.Save(path2); var loaded = Intermediate.Load(new[] { path1, path2 }); var loaded1 = loaded.First(); var loaded2 = loaded.Skip(1).Single(); var loadedSymbol1 = loaded1.Sections.Single().Symbols.Single(); var loadedSymbol2 = loaded2.Sections.Single().Symbols.Single(); Assert.True(loadedSymbol1.Definition.HasTag("customDef")); Assert.Equal("foo", loadedSymbol1.AsString(0)); Assert.Equal(2, loadedSymbol1[1].AsNumber()); Assert.True(loadedSymbol1[2].AsBool()); Assert.True(loadedSymbol1.HasTag("symbol1tag")); Assert.True(loadedSymbol2.Definition.HasTag("customDef2")); Assert.True(loadedSymbol2.Definition.HasTag("customDef2 tag2")); Assert.Equal("bar", loadedSymbol2.AsString(0)); Assert.Equal(3, loadedSymbol2[1].AsNumber()); Assert.False(loadedSymbol2[2].AsBool()); Assert.Equal("baz", loadedSymbol2.AsString(3)); Assert.True(loadedSymbol2.HasTag("symbol2tag1")); Assert.True(loadedSymbol2.HasTag("symbol2tag2")); } finally { File.Delete(path2); File.Delete(path1); } }
private void Run() { // Create the preprocessor and compiler Preprocessor preprocessor = new Preprocessor(); //preprocessor.Message += new MessageEventHandler(this.messageHandler.Display); preprocessor.CurrentPlatform = this.commandLine.Platform; foreach (string includePath in this.commandLine.IncludeSearchPaths) { preprocessor.IncludeSearchPaths.Add(includePath); } foreach (IPreprocessorExtension pe in this.preprocessorExtensions) { preprocessor.AddExtension(pe); } Compiler compiler = new Compiler(); //compiler.Message += new MessageEventHandler(this.messageHandler.Display); compiler.ShowPedanticMessages = this.commandLine.ShowPedanticMessages; compiler.CurrentPlatform = this.commandLine.Platform; foreach (IExtensionData ed in this.extensionData) { compiler.AddExtensionData(ed); } foreach (ICompilerExtension ce in this.compilerExtensions) { compiler.AddExtension(ce); } // Preprocess then compile each source file. foreach (CompileFile file in this.commandLine.Files) { // print friendly message saying what file is being compiled Console.WriteLine(file.SourcePath); // preprocess the source XDocument sourceDocument; try { if (!String.IsNullOrEmpty(this.commandLine.PreprocessFile)) { preprocessor.PreprocessOut = this.commandLine.PreprocessFile.Equals("con:", StringComparison.OrdinalIgnoreCase) ? Console.Out : new StreamWriter(this.commandLine.PreprocessFile); } sourceDocument = preprocessor.Process(file.SourcePath, this.commandLine.PreprocessorVariables); } finally { if (null != preprocessor.PreprocessOut && Console.Out != preprocessor.PreprocessOut) { preprocessor.PreprocessOut.Close(); } } // If we're not actually going to compile anything, move on to the next file. if (null == sourceDocument || !String.IsNullOrEmpty(this.commandLine.PreprocessFile)) { continue; } // and now we do what we came here to do... Intermediate intermediate = compiler.Compile(sourceDocument); // save the intermediate to disk if no errors were found for this source file if (null != intermediate) { intermediate.Save(file.OutputPath); } } }
public void Execute() { var section = this.Intermediate.Sections.Single(); var fileTransfers = new List <FileTransfer>(); var containsMergeModules = false; var suppressedTableNames = new HashSet <string>(); // If there are any fields to resolve later, create the cache to populate during bind. var variableCache = this.DelayedFields.Any() ? new Dictionary <string, string>(StringComparer.InvariantCultureIgnoreCase) : null; // Process the summary information table before the other tables. bool compressed; bool longNames; int installerVersion; string modularizationGuid; { var command = new BindSummaryInfoCommand(section); command.Execute(); compressed = command.Compressed; longNames = command.LongNames; installerVersion = command.InstallerVersion; modularizationGuid = command.ModularizationGuid; } // Add binder variables for all properties. if (SectionType.Product == section.Type || variableCache != null) { foreach (var propertyRow in section.Tuples.OfType <PropertyTuple>()) { // Set the ProductCode if it is to be generated. if ("ProductCode".Equals(propertyRow.Property, StringComparison.Ordinal) && "*".Equals(propertyRow.Value, StringComparison.Ordinal)) { propertyRow.Value = Common.GenerateGuid(); #if TODO_FIX_INSTANCE_TRANSFORM // Is this still necessary? // Update the target ProductCode in any instance transforms. foreach (SubStorage subStorage in this.Output.SubStorages) { Output subStorageOutput = subStorage.Data; if (OutputType.Transform != subStorageOutput.Type) { continue; } Table instanceSummaryInformationTable = subStorageOutput.Tables["_SummaryInformation"]; foreach (Row row in instanceSummaryInformationTable.Rows) { if ((int)SummaryInformation.Transform.ProductCodes == row.FieldAsInteger(0)) { row[1] = row.FieldAsString(1).Replace("*", propertyRow.Value); break; } } } #endif } // Add the property name and value to the variableCache. if (variableCache != null) { var key = String.Concat("property.", propertyRow.Property); variableCache[key] = propertyRow.Value; } } } // Sequence all the actions. { var command = new SequenceActionsCommand(section); command.Messaging = this.Messaging; command.Execute(); } { var command = new CreateSpecialPropertiesCommand(section); command.Execute(); } #if TODO_FINISH_PATCH ////if (OutputType.Patch == this.Output.Type) ////{ //// foreach (SubStorage substorage in this.Output.SubStorages) //// { //// Output transform = substorage.Data; //// ResolveFieldsCommand command = new ResolveFieldsCommand(); //// command.Tables = transform.Tables; //// command.FilesWithEmbeddedFiles = filesWithEmbeddedFiles; //// command.FileManagerCore = this.FileManagerCore; //// command.FileManagers = this.FileManagers; //// command.SupportDelayedResolution = false; //// command.TempFilesLocation = this.TempFilesLocation; //// command.WixVariableResolver = this.WixVariableResolver; //// command.Execute(); //// this.MergeUnrealTables(transform.Tables); //// } ////} #endif if (this.Messaging.EncounteredError) { return; } this.Messaging.Write(VerboseMessages.UpdatingFileInformation()); // This must occur after all variables and source paths have been resolved. List <FileFacade> fileFacades; { var command = new GetFileFacadesCommand(section); command.Execute(); fileFacades = command.FileFacades; } // Extract files that come from binary .wixlibs and WixExtensions (this does not extract files from merge modules). { var command = new ExtractEmbeddedFilesCommand(this.ExpectedEmbeddedFiles); command.Execute(); } // Gather information about files that do not come from merge modules. { var command = new UpdateFileFacadesCommand(this.Messaging, section); command.FileFacades = fileFacades; command.UpdateFileFacades = fileFacades.Where(f => !f.FromModule); command.OverwriteHash = true; command.TableDefinitions = this.TableDefinitions; command.VariableCache = variableCache; command.Execute(); } // Now that the variable cache is populated, resolve any delayed fields. if (this.DelayedFields.Any()) { var command = new ResolveDelayedFieldsCommand(this.Messaging, this.DelayedFields, variableCache); command.Execute(); } // Set generated component guids. { var command = new CalculateComponentGuids(this.Messaging, section); command.Execute(); } // Retrieve file information from merge modules. if (SectionType.Product == section.Type) { var wixMergeTuples = section.Tuples.OfType <WixMergeTuple>().ToList(); if (wixMergeTuples.Any()) { containsMergeModules = true; var command = new ExtractMergeModuleFilesCommand(this.Messaging, section, wixMergeTuples); command.FileFacades = fileFacades; command.OutputInstallerVersion = installerVersion; command.SuppressLayout = this.SuppressLayout; command.IntermediateFolder = this.IntermediateFolder; command.Execute(); fileFacades.AddRange(command.MergeModulesFileFacades); } } #if TODO_FINISH_PATCH else if (OutputType.Patch == this.Output.Type) { // Merge transform data into the output object. IEnumerable <FileFacade> filesFromTransform = this.CopyFromTransformData(this.Output); fileFacades.AddRange(filesFromTransform); } #endif // stop processing if an error previously occurred if (this.Messaging.EncounteredError) { return; } // Assign files to media. Dictionary <int, MediaTuple> assignedMediaRows; Dictionary <MediaTuple, IEnumerable <FileFacade> > filesByCabinetMedia; IEnumerable <FileFacade> uncompressedFiles; { var command = new AssignMediaCommand(section, this.Messaging); command.FileFacades = fileFacades; command.FilesCompressed = compressed; command.Execute(); assignedMediaRows = command.MediaRows; filesByCabinetMedia = command.FileFacadesByCabinetMedia; uncompressedFiles = command.UncompressedFileFacades; } // stop processing if an error previously occurred if (this.Messaging.EncounteredError) { return; } // Time to create the output object. Try to put as much above here as possible, updating the IR is better. Output output; { var command = new CreateOutputFromIRCommand(section, this.TableDefinitions, this.BackendExtensions); command.Execute(); output = command.Output; } // Update file sequence. { var command = new UpdateMediaSequencesCommand(output, fileFacades, assignedMediaRows); command.Execute(); } // Modularize identifiers. if (OutputType.Module == output.Type) { var command = new ModularizeCommand(output, modularizationGuid, section.Tuples.OfType <WixSuppressModularizationTuple>()); command.Execute(); } else // we can create instance transforms since Component Guids are set. { #if TODO_FIX_INSTANCE_TRANSFORM this.CreateInstanceTransforms(this.Output); #endif } #if TODO_FINISH_UPDATE // Extended binder extensions can be called now that fields are resolved. { Table updatedFiles = this.Output.EnsureTable(this.TableDefinitions["WixBindUpdatedFiles"]); foreach (IBinderExtension extension in this.Extensions) { extension.AfterResolvedFields(this.Output); } List <FileFacade> updatedFileFacades = new List <FileFacade>(); foreach (Row updatedFile in updatedFiles.Rows) { string updatedId = updatedFile.FieldAsString(0); FileFacade updatedFacade = fileFacades.First(f => f.File.File.Equals(updatedId)); updatedFileFacades.Add(updatedFacade); } if (updatedFileFacades.Any()) { UpdateFileFacadesCommand command = new UpdateFileFacadesCommand(); command.FileFacades = fileFacades; command.UpdateFileFacades = updatedFileFacades; command.ModularizationGuid = modularizationGuid; command.Output = this.Output; command.OverwriteHash = true; command.TableDefinitions = this.TableDefinitions; command.VariableCache = variableCache; command.Execute(); } } #endif // Stop processing if an error previously occurred. if (this.Messaging.EncounteredError) { return; } // Ensure the intermediate folder is created since delta patches will be // created there. Directory.CreateDirectory(this.IntermediateFolder); if (SectionType.Patch == section.Type && this.DeltaBinaryPatch) { var command = new CreateDeltaPatchesCommand(fileFacades, this.IntermediateFolder, section.Tuples.OfType <WixPatchIdTuple>().FirstOrDefault()); command.Execute(); } // create cabinet files and process uncompressed files var layoutDirectory = Path.GetDirectoryName(this.OutputPath); if (!this.SuppressLayout || OutputType.Module == output.Type) { this.Messaging.Write(VerboseMessages.CreatingCabinetFiles()); var command = new CreateCabinetsCommand(); command.CabbingThreadCount = this.CabbingThreadCount; command.CabCachePath = this.CabCachePath; command.DefaultCompressionLevel = this.DefaultCompressionLevel; command.Output = output; command.Messaging = this.Messaging; command.BackendExtensions = this.BackendExtensions; command.LayoutDirectory = layoutDirectory; command.Compressed = compressed; command.FileRowsByCabinet = filesByCabinetMedia; command.ResolveMedia = this.ResolveMedia; command.TableDefinitions = this.TableDefinitions; command.TempFilesLocation = this.IntermediateFolder; command.WixMediaTuples = section.Tuples.OfType <WixMediaTuple>(); command.Execute(); fileTransfers.AddRange(command.FileTransfers); } #if TODO_FINISH_PATCH if (OutputType.Patch == this.Output.Type) { // copy output data back into the transforms this.CopyToTransformData(this.Output); } #endif this.ValidateComponentGuids(output); // stop processing if an error previously occurred if (this.Messaging.EncounteredError) { return; } // Generate database file. this.Messaging.Write(VerboseMessages.GeneratingDatabase()); string tempDatabaseFile = Path.Combine(this.IntermediateFolder, Path.GetFileName(this.OutputPath)); this.GenerateDatabase(output, tempDatabaseFile, false, false); if (FileTransfer.TryCreate(tempDatabaseFile, this.OutputPath, true, output.Type.ToString(), null, out var transfer)) // note where this database needs to move in the future { transfer.Built = true; fileTransfers.Add(transfer); } // Stop processing if an error previously occurred. if (this.Messaging.EncounteredError) { return; } // Merge modules. if (containsMergeModules) { this.Messaging.Write(VerboseMessages.MergingModules()); // Add back possibly suppressed sequence tables since all sequence tables must be present // for the merge process to work. We'll drop the suppressed sequence tables again as // necessary. foreach (SequenceTable sequence in Enum.GetValues(typeof(SequenceTable))) { var sequenceTableName = sequence.ToString(); var sequenceTable = output.Tables[sequenceTableName]; if (null == sequenceTable) { sequenceTable = output.EnsureTable(this.TableDefinitions[sequenceTableName]); } if (0 == sequenceTable.Rows.Count) { suppressedTableNames.Add(sequenceTableName); } } var command = new MergeModulesCommand(); command.FileFacades = fileFacades; command.Output = output; command.OutputPath = tempDatabaseFile; command.SuppressedTableNames = suppressedTableNames; command.Execute(); } if (this.Messaging.EncounteredError) { return; } #if TODO_FINISH_VALIDATION // Validate the output if there is an MSI validator. if (null != this.Validator) { Stopwatch stopwatch = Stopwatch.StartNew(); // set the output file for source line information this.Validator.Output = this.Output; Messaging.Instance.Write(WixVerboses.ValidatingDatabase()); this.Validator.Validate(tempDatabaseFile); stopwatch.Stop(); Messaging.Instance.Write(WixVerboses.ValidatedDatabase(stopwatch.ElapsedMilliseconds)); // Stop processing if an error occurred. if (Messaging.Instance.EncounteredError) { return; } } #endif // Process uncompressed files. if (!this.Messaging.EncounteredError && !this.SuppressLayout && uncompressedFiles.Any()) { var command = new ProcessUncompressedFilesCommand(section); command.Compressed = compressed; command.FileFacades = uncompressedFiles; command.LayoutDirectory = layoutDirectory; command.LongNamesInImage = longNames; command.ResolveMedia = this.ResolveMedia; command.DatabasePath = tempDatabaseFile; command.Execute(); fileTransfers.AddRange(command.FileTransfers); } this.FileTransfers = fileTransfers; this.ContentFilePaths = fileFacades.Select(r => r.WixFile.Source.Path).ToList(); this.Pdb = new Pdb { Output = output }; // TODO: Eventually this gets removed var intermediate = new Intermediate(this.Intermediate.Id, new[] { section }, this.Intermediate.Localizations.ToDictionary(l => l.Culture, StringComparer.OrdinalIgnoreCase), this.Intermediate.EmbedFilePaths); intermediate.Save(Path.ChangeExtension(this.OutputPath, "wir")); }
/// <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 { // 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.sourceFiles.Count) { this.showHelp = true; } else if (1 < this.sourceFiles.Count && null != this.outputFile) { throw new ArgumentException("cannot specify more than one source file with single output file. Either specify an output directory for the -out argument by ending the argument with a '\\' or remove the -out argument to have the source files compiled to the current directory.", "-out"); } if (this.showLogo) { Assembly candleAssembly = Assembly.GetExecutingAssembly(); Console.WriteLine("Microsoft (R) Windows Installer Xml Compiler version {0}", candleAssembly.GetName().Version.ToString()); Console.WriteLine("Copyright (C) Microsoft Corporation 2003. All rights reserved."); Console.WriteLine(); } if (this.showHelp) { Console.WriteLine(" usage: candle.exe [-?] [-nologo] [-out outputFile] sourceFile [sourceFile ...]"); Console.WriteLine(); Console.WriteLine(" -d<name>=<value> define a parameter for the preprocessor"); Console.WriteLine(" -p<file> preprocess to a file (or stdout if no file supplied)"); Console.WriteLine(" -I<dir> add to include search path"); Console.WriteLine(" -nologo skip printing candle logo information"); Console.WriteLine(" -out specify output file (default: write to current directory)"); Console.WriteLine(" -pedantic show pedantic messages"); Console.WriteLine(" -ss suppress schema validation of documents (performance boost)"); Console.WriteLine(" -trace show source trace for errors, warnings, and verbose messages"); Console.WriteLine(" -ext extension assembly or \"class, assembly\""); Console.WriteLine(" -zs only do validation of documents (no output)"); Console.WriteLine(" -wx treat warnings as errors"); Console.WriteLine(" -sw<N> suppress warning with specific message ID"); 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(" .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(" .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 preprocessor and compiler Preprocessor preprocessor = new Preprocessor(); preprocessor.Message += new MessageEventHandler(this.messageHandler.Display); for (int i = 0; i < this.includeSearchPaths.Count; ++i) { preprocessor.IncludeSearchPaths.Add(this.includeSearchPaths[i]); } Compiler compiler = new Compiler(); compiler.Message += new MessageEventHandler(this.messageHandler.Display); compiler.ShowPedanticMessages = this.showPedanticMessages; compiler.SuppressValidate = this.suppressSchema; // load any extensions foreach (string extension in this.extensionList) { WixExtension wixExtension = WixExtension.Load(extension); preprocessor.AddExtension(wixExtension); compiler.AddExtension(wixExtension); } // preprocess then compile each source file foreach (string sourceFile in this.sourceFiles) { string sourceFileName = Path.GetFileName(sourceFile); string targetFile; if (null != this.outputFile) { targetFile = this.outputFile; } else if (null != this.outputDirectory) { targetFile = Path.Combine(this.outputDirectory, Path.ChangeExtension(sourceFileName, ".wixobj")); } else { targetFile = Path.ChangeExtension(sourceFileName, ".wixobj"); } // print friendly message saying what file is being compiled Console.WriteLine(sourceFileName); // preprocess the source XmlDocument sourceDocument; try { if (this.preprocessToStdout) { preprocessor.PreprocessOut = Console.Out; } else if (null != this.preprocessFile) { preprocessor.PreprocessOut = new StreamWriter(this.preprocessFile); } sourceDocument = preprocessor.Process(Path.GetFullPath(sourceFile), this.parameters); } finally { if (null != preprocessor.PreprocessOut && Console.Out != preprocessor.PreprocessOut) { preprocessor.PreprocessOut.Close(); } } // if we're not actually going to compile anything, move on to the next file if (this.schemaOnly || null == sourceDocument || this.preprocessToStdout || null != this.preprocessFile) { continue; } // and now we do what we came here to do... Intermediate intermediate = compiler.Compile(sourceDocument); // save the intermediate to disk if no errors were found for this source file if (null != intermediate) { intermediate.Save(targetFile); } } } 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); }