예제 #1
0
        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);
            }
        }
예제 #2
0
        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);
        }
예제 #3
0
        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);
        }
예제 #4
0
        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);
        }
예제 #5
0
        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);
            }
        }
예제 #6
0
        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);
            }
        }
예제 #7
0
        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);
            }
        }
예제 #8
0
        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);
        }
예제 #9
0
        /// <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());
        }
예제 #10
0
        /// <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);
        }
예제 #11
0
        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);
            }
        }
예제 #12
0
        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);
                }
            }
        }
예제 #13
0
        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"));
        }
예제 #14
0
        /// <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);
        }