Exemplo n.º 1
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
            {
                XmlSchemaCollection objectSchema = new XmlSchemaCollection();
                FileInfo            currentFile  = null;

                ArrayList intermediates = new ArrayList();
                Linker    linker        = null;
                Microsoft.Tools.WindowsInstallerXml.Binder binder = null;
                Localizer localizer = null;

                try
                {
                    // parse the command line
                    this.ParseCommandLine(args);

                    // exit if there was an error parsing the command line (otherwise the logo appears after error messages)
                    if (this.messageHandler.FoundError)
                    {
                        return(this.messageHandler.PostProcess());
                    }

                    if (0 == this.objectFiles.Count)
                    {
                        this.showHelp = true;
                    }
                    else if (null == this.outputFile)
                    {
                        if (1 < this.objectFiles.Count)
                        {
                            throw new ArgumentException("must specify output file when using more than one input file", "-out");
                        }

                        FileInfo fi = (FileInfo)this.objectFiles[0];
                        this.outputFile = new FileInfo(Path.ChangeExtension(fi.Name, ".wix"));                           // we'll let the linker change the extension later
                    }

                    if (this.showLogo)
                    {
                        Assembly lightAssembly = Assembly.GetExecutingAssembly();

                        Console.WriteLine("Microsoft (R) Windows Installer Xml Linker version {0}", lightAssembly.GetName().Version.ToString());
                        Console.WriteLine("Copyright (C) Microsoft Corporation 2003. All rights reserved.");
                        Console.WriteLine();
                    }

                    if (this.showHelp)
                    {
                        Console.WriteLine(" usage:  light.exe [-?] [-b basePath] [-nologo] [-out outputFile] objectFile [objectFile ...]");
                        Console.WriteLine();
                        Console.WriteLine("   -ai        allow identical rows, identical rows will be treated as a warning");
                        Console.WriteLine("   -au        (experimental) allow unresolved references, will not create a valid output");
                        Console.WriteLine("   -b         base path to locate all files (default: current directory)");
                        Console.WriteLine("   -cc        path to cache built cabinets (will not be deleted after linking)");
                        Console.WriteLine("   -ext       extension (class, assembly), should extend SchemaExtension or BinderExtension");
                        Console.WriteLine("   -fv        add a 'fileVersion' entry to the MsiAssemblyName table (rarely needed)");
                        Console.WriteLine("   -i         specify the base output path for uncompressed images (default: -out parameter)");
                        Console.WriteLine("   -loc       read localization string sfrom .wxl file");
                        Console.WriteLine("   -nologo    skip printing light logo information");
                        Console.WriteLine("   -notidy    do not delete temporary files (useful for debugging)");
                        Console.WriteLine("   -reusecab  reuse cabinets from cabinet cache");
                        Console.WriteLine("   -out       specify output file (default: write to current directory)");
                        Console.WriteLine("   -xo        output xml instead of MSI format");
                        Console.WriteLine("   -pedantic:<level>  pedantic checks (levels: easy, heroic, legendary)");
                        Console.WriteLine("   -reusecab  reuse cabinets from cabinet cache");
                        Console.WriteLine("   -sa        suppress assemblies: do not get assembly name information for assemblies");
                        Console.WriteLine("   -sacl      suppress resetting ACLs (useful when laying out image to a network share)");
                        Console.WriteLine("   -sadmin    suppress default admin sequence actions");
                        Console.WriteLine("   -sadv      suppress default adv sequence actions");
                        Console.WriteLine("   -sa        suppress assemblys: do not get assembly name information for assemblies");
                        Console.WriteLine("   -sf        suppress files: do not get any file information (equivalent to -sa and -sh)");
                        Console.WriteLine("   -sh        suppress file info: do not get hash, version, language, etc");
                        Console.WriteLine("   -sl        suppress layout");
                        Console.WriteLine("   -ss        suppress schema validation of documents (performance boost)");
                        Console.WriteLine("   -sui       suppress default UI sequence actions");
                        Console.WriteLine("   -sv        suppress intermediate file version mismatch checking");
                        Console.WriteLine("   -ts        tag sectionId attribute on tuples (ignored if not used with -xo)");
                        Console.WriteLine("   -ust       use small table definitions (for backwards compatiblity)");
                        Console.WriteLine("   -wx        treat warnings as errors");
                        Console.WriteLine("   -w<N>      set the warning level (0: show all, 3: show none)");
                        Console.WriteLine("   -sw        suppress all warnings (same as -w3)");
                        Console.WriteLine("   -sw<N>     suppress warning with specific message ID");
                        Console.WriteLine("   -v         verbose output (same as -v2)");
                        Console.WriteLine("   -v<N>      sets the level of verbose output (0: most output, 3: none)");
                        Console.WriteLine("   -?         this help information");
                        Console.WriteLine();
                        Console.WriteLine("Environment variables:");
                        Console.WriteLine("   WIX_TEMP   overrides the temporary directory used for cab creation, msm exploding, ...");
                        Console.WriteLine();
                        Console.WriteLine("Common extensions:");
                        Console.WriteLine("   .wxs    - Windows installer Xml Source file");
                        Console.WriteLine("   .wxi    - Windows installer Xml Include file");
                        Console.WriteLine("   .wxl    - Windows installer Xml Localization file");
                        Console.WriteLine("   .wixobj - Windows installer Xml Object file (in XML format)");
                        Console.WriteLine("   .wixlib - Windows installer Xml Library file (in XML format)");
                        Console.WriteLine("   .wixout - Windows installer Xml Output file (in XML format)");
                        Console.WriteLine();
                        Console.WriteLine("   .msm - Windows installer Merge Module");
                        Console.WriteLine("   .msi - Windows installer Product Database");
                        Console.WriteLine("   .mst - Windows installer Transform");
                        Console.WriteLine("   .pcp - Windows installer Patch Creation Package");
                        Console.WriteLine();
                        Console.WriteLine("For more information see: http://wix.sourceforge.net");

                        return(this.messageHandler.PostProcess());
                    }

                    // create the linker and the binder
                    linker = new Linker(this.useSmallTables);
                    binder = new Microsoft.Tools.WindowsInstallerXml.Binder(this.useSmallTables);

                    linker.AllowIdenticalRows        = this.allowIdenticalRows;
                    linker.AllowUnresolvedReferences = this.allowUnresolvedReferences;
                    linker.PedanticLevel             = this.pedanticLevel;

                    // set the sequence suppression options
                    linker.SuppressAdminSequence     = this.suppressAdminSequence;
                    linker.SuppressAdvertiseSequence = this.suppressAdvertiseSequence;
                    linker.SuppressUISequence        = this.suppressUISequence;

                    linker.SectionIdOnTuples             = this.sectionIdOnTuples;
                    binder.SuppressAclReset              = this.suppressAclReset;
                    binder.SetMsiAssemblyNameFileVersion = this.setMsiAssemblyNameFileVersion;
                    binder.SuppressAssemblies            = this.suppressAssemblies;
                    binder.SuppressFileHashAndInfo       = this.suppressFileHashAndInfo;

                    if (this.suppressFiles)
                    {
                        binder.SuppressAssemblies      = true;
                        binder.SuppressFileHashAndInfo = true;
                    }

                    binder.SuppressLayout    = this.suppressLayout;
                    binder.TempFilesLocation = Environment.GetEnvironmentVariable("WIX_TEMP");

                    if (null != this.cabCachePath || this.reuseCabinets)
                    {
                        // ensure the cabinet cache path exists if we are going to use it
                        if (null != this.cabCachePath && !Directory.Exists(this.cabCachePath))
                        {
                            Directory.CreateDirectory(this.cabCachePath);
                        }
                    }

                    if (null != this.basePaths)
                    {
                        foreach (string basePath in this.basePaths)
                        {
                            this.sourcePaths.Add(basePath);
                        }
                    }

                    // load any extensions
                    bool binderExtensionLoaded = false;
                    foreach (string extension in this.extensionList)
                    {
                        Type extensionType = Type.GetType(extension);
                        if (null == extensionType)
                        {
                            throw new WixInvalidExtensionException(extension);
                        }

                        if (extensionType.IsSubclassOf(typeof(BinderExtension)))
                        {
                            object[]        extensionArgs   = new object[] { this.basePaths, this.cabCachePath, this.reuseCabinets, this.sourcePaths };
                            BinderExtension binderExtension = Activator.CreateInstance(extensionType, extensionArgs) as BinderExtension;
                            Debug.Assert(null != binderExtension);
                            if (binderExtensionLoaded)
                            {
                                throw new ArgumentException(String.Format(CultureInfo.InvariantCulture, "cannot load binder extension: {0}.  light can only load one binder extension and has already loaded binder extension: {1}.", binderExtension.ToString(), binder.Extension.ToString()), "ext");
                            }

                            binder.Extension      = binderExtension;
                            binderExtensionLoaded = true;
                        }
                        else if (extensionType.IsSubclassOf(typeof(SchemaExtension)))
                        {
                            linker.AddExtension((SchemaExtension)Activator.CreateInstance(extensionType));
                        }
                        else
                        {
                            throw new WixInvalidExtensionException(extension, extensionType, typeof(BinderExtension), typeof(SchemaExtension));
                        }
                    }

                    // if the binder extension has not been loaded yet use the built-in binder extension
                    if (!binderExtensionLoaded)
                    {
                        binder.Extension = new LightBinderExtension(this.basePaths, this.cabCachePath, this.reuseCabinets, this.sourcePaths);
                    }

                    if (null != this.imagebaseOutputPath)
                    {
                        binder.ImageBaseOutputPath = this.imagebaseOutputPath;
                    }

                    // set the message handlers
                    linker.Message += new MessageEventHandler(this.messageHandler.Display);
                    binder.Message += new MessageEventHandler(this.messageHandler.Display);

                    // load the object schema
                    if (!this.suppressSchema)
                    {
                        Assembly wixAssembly = Assembly.Load("wix");

                        using (Stream objectsSchemaStream = wixAssembly.GetManifestResourceStream("Microsoft.Tools.WindowsInstallerXml.Xsd.objects.xsd"))
                        {
                            XmlReader reader = new XmlTextReader(objectsSchemaStream);
                            objectSchema.Add("http://schemas.microsoft.com/wix/2003/04/objects", reader);
                        }
                    }

                    Output output = null;

                    // loop through all the believed object files
                    foreach (FileInfo objectFile in this.objectFiles)
                    {
                        currentFile = objectFile;
                        string dirName = Path.GetDirectoryName(currentFile.FullName);
                        if (!StringArrayContains(this.sourcePaths, dirName))
                        {
                            this.sourcePaths.Add(dirName);
                        }

                        // load the object file into an intermediate object and add it to the list to be linked
                        using (Stream fileStream = new FileStream(currentFile.FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                        {
                            XmlReader fileReader = new XmlTextReader(fileStream);

                            try
                            {
                                XmlReader intermediateReader = fileReader;
                                if (!this.suppressSchema)
                                {
                                    intermediateReader = new XmlValidatingReader(fileReader);
                                    ((XmlValidatingReader)intermediateReader).Schemas.Add(objectSchema);
                                }

                                Intermediate intermediate = Intermediate.Load(intermediateReader, currentFile.FullName, linker.TableDefinitions, this.suppressVersionCheck);
                                intermediates.Add(intermediate);
                                continue;                                 // next file
                            }
                            catch (WixNotIntermediateException)
                            {
                                // try another format
                            }

                            try
                            {
                                Library library = Library.Load(currentFile.FullName, linker.TableDefinitions, this.suppressVersionCheck);
                                intermediates.AddRange(library.Intermediates);
                                continue;                                 // next file
                            }
                            catch (WixNotLibraryException)
                            {
                                // try another format
                            }

                            output = Output.Load(currentFile.FullName, this.suppressVersionCheck);
                        }
                    }

                    // instantiate the localizer and load any wixloc files
                    if (0 < this.localizationFiles.Count || !this.outputXml)
                    {
                        localizer = new Localizer();

                        localizer.Message += new MessageEventHandler(this.messageHandler.Display);

                        // load each wixloc file
                        foreach (string localizationFile in this.localizationFiles)
                        {
                            localizer.LoadFromFile(localizationFile);
                        }

                        // immediately stop processing if any errors were found
                        if (this.messageHandler.FoundError)
                        {
                            return(this.messageHandler.PostProcess());
                        }
                    }

                    // and now for the fun part
                    currentFile = this.outputFile;
                    if (null == output)
                    {
                        // tell the linker about the localizer
                        linker.Localizer = localizer;
                        localizer        = null;

                        output = linker.Link((Intermediate[])intermediates.ToArray(typeof(Intermediate)));

                        // if an error occurred during linking, stop processing
                        if (null == output)
                        {
                            return(this.messageHandler.PostProcess());
                        }
                    }
                    else if (0 != intermediates.Count)
                    {
                        throw new InvalidOperationException("Cannot link object files (.wixobj) files with an output file (.wixout)");
                    }

                    output.Path = this.outputFile.FullName;

                    // only output the xml
                    if (this.outputXml)
                    {
                        string outputExtension = Path.GetExtension(this.outputFile.FullName);
                        if (null == outputExtension || 0 == outputExtension.Length || ".wix" == outputExtension)
                        {
                            output.Path = Path.ChangeExtension(this.outputFile.FullName, ".wixout");
                        }
                        output.Save();
                    }
                    else                     // finish creating the MSI/MSM
                    {
                        string outputExtension = Path.GetExtension(this.outputFile.FullName);
                        if (null == outputExtension || 0 == outputExtension.Length || ".wix" == outputExtension)
                        {
                            if (OutputType.Module == output.Type)
                            {
                                output.Path = Path.ChangeExtension(this.outputFile.FullName, ".msm");
                            }
                            else if (OutputType.PatchCreation == output.Type)
                            {
                                output.Path = Path.ChangeExtension(this.outputFile.FullName, ".pcp");
                            }
                            else
                            {
                                output.Path = Path.ChangeExtension(this.outputFile.FullName, ".msi");
                            }
                        }

                        // tell the binder about the localizer
                        binder.Localizer = localizer;

                        binder.Bind(output);
                    }

                    currentFile = null;
                }
                catch (WixInvalidIdtException)
                {
                    this.tidy = false;                       // make sure the IDT files stay around
                    throw;
                }
                catch (WixMergeFailureException)
                {
                    this.tidy = false;                     // make sure the merge.log stays around
                    throw;
                }
                finally
                {
                    if (null != binder)
                    {
                        if (this.tidy)
                        {
                            if (!binder.DeleteTempFiles())
                            {
                                Console.WriteLine("Warning, failed to delete temporary directory: {0}", binder.TempFilesLocation);
                            }
                        }
                        else
                        {
                            Console.WriteLine("Temporary directory located at '{0}'.", binder.TempFilesLocation);
                        }
                    }
                }
            }
            catch (WixException we)
            {
                // TODO: once all WixExceptions are converted to errors, this clause
                // should be a no-op that just catches WixFatalErrorException's
                this.messageHandler.Display("light.exe", "LGHT", we);
                return(1);
            }
            catch (Exception e)
            {
                this.OnMessage(WixErrors.UnexpectedException(e.Message, e.GetType().ToString(), e.StackTrace));
                if (e is NullReferenceException || e is SEHException)
                {
                    throw;
                }
            }

            return(this.messageHandler.PostProcess());
        }
Exemplo n.º 2
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)
        {
            Microsoft.Tools.WindowsInstallerXml.Binder binder = null;
            Differ   differ   = null;
            Unbinder unbinder = null;

            TempFileCollection tempFileCollection = null;

            try
            {
                // parse the command line
                this.ParseCommandLine(args);

                // validate the inputs
                if (this.xmlInputs && this.adminImage)
                {
                    this.messageHandler.Display(this, WixErrors.IllegalCommandlineArgumentCombination("a", "xi"));
                    this.showHelp = true;
                }

                string[] allValidExtensions               = new string[] { wixMstExtension, wixOutExtension, wixPdbExtension, msiExtension };
                string[] expectedSingleInputExtensions    = new string[] { wixMstExtension, wixOutExtension };
                string[] expectedDoubleInputXmlExtensions = new string[] { wixOutExtension, wixPdbExtension };
                string[] expectedDoubleInputMsiExtensions = new string[] { msiExtension };

                // Validate that all inputs have the correct extension and we dont have too many inputs.
                if (1 == this.inputFiles.Count)
                {
                    string inputFile = this.inputFiles[0];

                    bool hasValidExtension = false;
                    foreach (string extension in expectedSingleInputExtensions)
                    {
                        if (String.Equals(Path.GetExtension(inputFile), extension, StringComparison.OrdinalIgnoreCase))
                        {
                            hasValidExtension = true;
                            break;
                        }
                    }

                    if (!hasValidExtension)
                    {
                        bool missingInput = false;

                        // Check if its using an extension that could be valid in other scenarios.
                        foreach (string validExtension in allValidExtensions)
                        {
                            if (String.Equals(Path.GetExtension(inputFile), validExtension, StringComparison.OrdinalIgnoreCase))
                            {
                                this.messageHandler.Display(this, WixErrors.WrongFileExtensionForNumberOfInputs(Path.GetExtension(inputFile), inputFile));
                                missingInput = true;
                                break;
                            }
                        }

                        if (!missingInput)
                        {
                            this.messageHandler.Display(this, WixErrors.UnexpectedFileExtension(inputFile, String.Join(", ", expectedSingleInputExtensions)));
                        }
                    }
                }
                else if (2 == this.inputFiles.Count)
                {
                    foreach (string inputFile in inputFiles)
                    {
                        bool     hasValidExtension  = false;
                        string[] expectedExtensions = allValidExtensions;
                        if (this.xmlInputs)
                        {
                            foreach (string extension in expectedDoubleInputXmlExtensions)
                            {
                                if (String.Equals(Path.GetExtension(inputFile), extension, StringComparison.OrdinalIgnoreCase))
                                {
                                    hasValidExtension  = true;
                                    expectedExtensions = expectedDoubleInputXmlExtensions;
                                    break;
                                }
                            }
                        }
                        else
                        {
                            foreach (string extension in expectedDoubleInputMsiExtensions)
                            {
                                if (String.Equals(Path.GetExtension(inputFile), extension, StringComparison.OrdinalIgnoreCase))
                                {
                                    hasValidExtension  = true;
                                    expectedExtensions = expectedDoubleInputMsiExtensions;
                                    break;
                                }
                            }
                        }

                        if (!hasValidExtension)
                        {
                            this.messageHandler.Display(this, WixErrors.UnexpectedFileExtension(inputFile, String.Join(", ", expectedExtensions)));
                        }
                    }
                }
                else
                {
                    this.showHelp = true;
                }

                // exit if there was an error parsing the command line or with a file extension (otherwise the logo appears after error messages)
                if (this.messageHandler.EncounteredError)
                {
                    return(this.messageHandler.LastErrorNumber);
                }

                if (null == this.outputFile)
                {
                    this.showHelp = true;
                }

                if (this.showLogo)
                {
                    AppCommon.DisplayToolHeader();
                }

                if (this.showHelp)
                {
                    Console.WriteLine(TorchStrings.HelpMessage);
                    AppCommon.DisplayToolFooter();
                    return(this.messageHandler.LastErrorNumber);
                }

                foreach (string parameter in this.invalidArgs)
                {
                    this.messageHandler.Display(this, WixWarnings.UnsupportedCommandLineArgument(parameter));
                }
                this.invalidArgs = null;

                binder   = new Microsoft.Tools.WindowsInstallerXml.Binder();
                differ   = new Differ();
                unbinder = new Unbinder();

                // load any extensions
                foreach (string extension in this.extensionList)
                {
                    WixExtension wixExtension = WixExtension.Load(extension);
                    unbinder.AddExtension(wixExtension);
                    binder.AddExtension(wixExtension);
                    differ.AddExtension(wixExtension);
                }

                binder.Message   += new MessageEventHandler(this.messageHandler.Display);
                differ.Message   += new MessageEventHandler(this.messageHandler.Display);
                unbinder.Message += new MessageEventHandler(this.messageHandler.Display);

                binder.TempFilesLocation   = Environment.GetEnvironmentVariable("WIX_TEMP");
                unbinder.TempFilesLocation = Environment.GetEnvironmentVariable("WIX_TEMP");
                tempFileCollection         = new TempFileCollection(Environment.GetEnvironmentVariable("WIX_TEMP"));

                binder.WixVariableResolver       = new WixVariableResolver();
                differ.PreserveUnchangedRows     = this.preserveUnchangedRows;
                differ.ShowPedanticMessages      = this.showPedanticMessages;
                unbinder.SuppressExtractCabinets = true;
                unbinder.IsAdminImage            = this.adminImage;

                if (null == this.exportBasePath)
                {
                    this.exportBasePath = tempFileCollection.BasePath;
                }

                // load and process the inputs
                Output transform;
                if (1 == this.inputFiles.Count)
                {
                    transform = Output.Load(this.inputFiles[0], false, false);
                    if (OutputType.Transform != transform.Type)
                    {
                        this.messageHandler.Display(this, WixErrors.InvalidWixTransform(this.inputFiles[0]));
                        return(this.messageHandler.LastErrorNumber);
                    }
                }
                else // 2 inputs
                {
                    Output targetOutput;
                    Output updatedOutput;

                    if (this.xmlInputs)
                    {
                        // load the target database
                        if (String.Equals(Path.GetExtension(inputFiles[0]), wixPdbExtension, StringComparison.OrdinalIgnoreCase))
                        {
                            Pdb targetPdb = Pdb.Load(this.inputFiles[0], false, false);
                            targetOutput = targetPdb.Output;
                        }
                        else
                        {
                            targetOutput = Output.Load(this.inputFiles[0], false, false);
                        }

                        // load the updated database
                        if (String.Equals(Path.GetExtension(inputFiles[1]), wixPdbExtension, StringComparison.OrdinalIgnoreCase))
                        {
                            Pdb updatedPdb = Pdb.Load(this.inputFiles[1], false, false);
                            updatedOutput = updatedPdb.Output;
                        }
                        else
                        {
                            updatedOutput = Output.Load(this.inputFiles[1], false, false);
                        }

                        this.xmlOutput = true;
                    }
                    else
                    {
                        // load the target database
                        targetOutput = unbinder.Unbind(this.inputFiles[0], OutputType.Product, Path.Combine(this.exportBasePath, "targetBinaries"));

                        // load the updated database
                        updatedOutput = unbinder.Unbind(this.inputFiles[1], OutputType.Product, Path.Combine(this.exportBasePath, "updatedBinaries"));
                    }

                    // diff the target and updated databases
                    transform = differ.Diff(targetOutput, updatedOutput, this.validationFlags);

                    if (null == transform.Tables || 0 >= transform.Tables.Count)
                    {
                        throw new WixException(WixErrors.NoDifferencesInTransform(transform.SourceLineNumbers));
                    }
                }

                // output the transform
                if (null != transform)
                {
                    // If either the user selected xml output or gave xml input, save as xml output.
                    // With xml inputs, many funtions of the binder have not been performed on the inputs (ie. file sequencing). This results in bad IDT files which cannot be put in a transform.
                    if (this.xmlOutput)
                    {
                        transform.Save(this.outputFile, null, null, tempFileCollection.BasePath);
                    }
                    else
                    {
                        binder.Bind(transform, this.outputFile);
                    }
                }
            }
            catch (WixException we)
            {
                if (we is WixInvalidIdtException)
                {
                    // make sure the IDT files stay around
                    this.tidy = false;
                }

                this.messageHandler.Display(this, we.Error);
            }
            catch (Exception e)
            {
                // make sure the files stay around for debugging
                this.tidy = false;

                this.messageHandler.Display(this, WixErrors.UnexpectedException(e.Message, e.GetType().ToString(), e.StackTrace));
                if (e is NullReferenceException || e is SEHException)
                {
                    throw;
                }
            }
            finally
            {
                if (null != binder)
                {
                    if (this.tidy)
                    {
                        if (!binder.DeleteTempFiles())
                        {
                            Console.WriteLine(TorchStrings.WAR_FailedToDeleteTempDir, binder.TempFilesLocation);
                        }
                    }
                    else
                    {
                        Console.WriteLine(TorchStrings.INF_BinderTempDirLocatedAt, binder.TempFilesLocation);
                    }
                }

                if (null != unbinder)
                {
                    if (this.tidy)
                    {
                        if (!unbinder.DeleteTempFiles())
                        {
                            Console.WriteLine(TorchStrings.WAR_FailedToDeleteTempDir, binder.TempFilesLocation);
                        }
                    }
                    else
                    {
                        Console.WriteLine(TorchStrings.INF_UnbinderTempDirLocatedAt, binder.TempFilesLocation);
                    }
                }

                if (null != tempFileCollection)
                {
                    if (this.tidy)
                    {
                        try
                        {
                            Directory.Delete(tempFileCollection.BasePath, true);
                        }
                        catch (DirectoryNotFoundException)
                        {
                            // if the path doesn't exist, then there is nothing for us to worry about
                        }
                        catch
                        {
                            Console.WriteLine(TorchStrings.WAR_FailedToDeleteTempDir, tempFileCollection.BasePath);
                        }
                    }
                    else
                    {
                        Console.WriteLine(TorchStrings.INF_TorchTempDirLocatedAt, tempFileCollection.BasePath);
                    }
                }
            }

            return(this.messageHandler.LastErrorNumber);
        }
Exemplo n.º 3
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)
        {
            Microsoft.Tools.WindowsInstallerXml.Binder binder = new Microsoft.Tools.WindowsInstallerXml.Binder();

            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 (null == this.inputFile || null == this.outputFile)
                {
                    this.showHelp = true;
                }

                if (this.showLogo)
                {
                    Assembly pyroAssembly = Assembly.GetExecutingAssembly();

                    Console.WriteLine("Microsoft (R) Windows Installer Xml Patch Builder Version {0}", pyroAssembly.GetName().Version.ToString());
                    Console.WriteLine("Copyright (C) Microsoft Corporation 2003. All rights reserved.\n");
                    Console.WriteLine();
                }

                if (this.showHelp)
                {
                    Console.WriteLine(" usage: pyro.exe [-?] [-nologo] inputFile -out outputFile [-t baseline wixTransform]");
                    Console.WriteLine();
                    Console.WriteLine("   -cc        path to cache built cabinets");
                    Console.WriteLine("   -ext       extension assembly or \"class, assembly\"");
                    Console.WriteLine("   -nologo    skip printing logo information");
                    Console.WriteLine("   -notidy    do not delete temporary files (useful for debugging)");
                    Console.WriteLine("   -out       specify output file");
                    Console.WriteLine("   -reusecab  reuse cabinets from cabinet cache");
                    Console.WriteLine("   -sa        suppress assemblies: do not get assembly name information for assemblies");
                    Console.WriteLine("   -sf        suppress files: do not get any file information (equivalent to -sa and -sh)");
                    Console.WriteLine("   -sh        suppress file info: do not get hash, version, language, etc");
                    Console.WriteLine("   -sw<N>     suppress warning with specific message ID");
                    Console.WriteLine("   -t baseline transform  one or more wix transforms and its baseline");
                    Console.WriteLine("   -v         verbose output");
                    Console.WriteLine("   -wx        treat warnings as errors");
                    Console.WriteLine("   -?         this help information");
                    Console.WriteLine();
                    Console.WriteLine("Environment variables:");
                    Console.WriteLine("   WIX_TEMP   overrides the temporary directory used for cab extraction, binary extraction, ...");
                    Console.WriteLine();
                    Console.WriteLine("Common extensions:");
                    Console.WriteLine("   .wxi    - Windows installer Xml Include file");
                    Console.WriteLine("   .wxl    - Windows installer Xml Localization file");
                    Console.WriteLine("   .wxs    - Windows installer Xml Source file");
                    Console.WriteLine("   .wixlib - Windows installer Xml Library file (in XML format)");
                    Console.WriteLine("   .wixobj - Windows installer Xml Object file (in XML format)");
                    Console.WriteLine("   .wixout - Windows installer Xml Output file (in XML format)");
                    Console.WriteLine();
                    Console.WriteLine("   .msi - Windows installer Product Database");
                    Console.WriteLine("   .msm - Windows installer Merge Module");
                    Console.WriteLine("   .msp - Windows installer Patch");
                    Console.WriteLine("   .mst - Windows installer Transform");
                    Console.WriteLine("   .pcp - Windows installer Patch Creation Package");
                    Console.WriteLine();
                    Console.WriteLine("For more information see: http://wix.sourceforge.net");

                    return(this.messageHandler.LastErrorNumber);
                }

                // Load the extension if one was passed on the command line.
                WixExtension wixExtension = null;
                if (null != this.extension)
                {
                    wixExtension = WixExtension.Load(extension);
                }

                // Load in transforms
                ArrayList transforms = new ArrayList();
                foreach (DictionaryEntry inputTransform in inputTransforms)
                {
                    Output         transformOutput = Output.Load(inputTransform.Key.ToString(), false, false);
                    PatchTransform patchTransform  = new PatchTransform(transformOutput, (string)inputTransform.Value);
                    transforms.Add(patchTransform);
                }

                // Load the patch
                Patch patch = new Patch();
                patch.Load(this.inputFile);

                // Copy transforms into output
                if (0 < transforms.Count)
                {
                    patch.AttachTransforms(transforms);
                }

                // Create and configure the binder
                binder = new Microsoft.Tools.WindowsInstallerXml.Binder();
                binder.TempFilesLocation       = Environment.GetEnvironmentVariable("WIX_TEMP");
                binder.WixVariableResolver     = this.wixVariableResolver;
                binder.Message                += new MessageEventHandler(this.messageHandler.Display);
                binder.SuppressAssemblies      = this.suppressAssemblies;
                binder.SuppressFileHashAndInfo = this.suppressFileHashAndInfo;

                if (this.suppressFiles)
                {
                    binder.SuppressAssemblies      = true;
                    binder.SuppressFileHashAndInfo = true;
                }

                // Load the extension if provided and set all its properties
                if (null != wixExtension)
                {
                    binder.Extension = wixExtension.BinderExtension;
                }

                if (null != this.cabCachePath || this.reuseCabinets)
                {
                    // ensure the cabinet cache path exists if we are going to use it
                    if (null != this.cabCachePath && !Directory.Exists(this.cabCachePath))
                    {
                        Directory.CreateDirectory(this.cabCachePath);
                    }
                }

                binder.Extension.ReuseCabinets = this.reuseCabinets;
                binder.Extension.CabCachePath  = this.cabCachePath;
                binder.Extension.Output        = patch.PatchOutput;

                // Bind the patch to an msp.
                binder.Bind(patch.PatchOutput, this.outputFile);
            }
            catch (WixException we)
            {
                this.OnMessage(we.Error);
            }
            catch (Exception e)
            {
                this.OnMessage(WixErrors.UnexpectedException(e.Message, e.GetType().ToString(), e.StackTrace));
                if (e is NullReferenceException || e is SEHException)
                {
                    throw;
                }
            }
            finally
            {
                if (null != binder)
                {
                    if (this.tidy)
                    {
                        if (!binder.DeleteTempFiles())
                        {
                            Console.WriteLine("Warning, failed to delete temporary directory: {0}", binder.TempFilesLocation);
                        }
                    }
                    else
                    {
                        Console.WriteLine("Temporary directory located at '{0}'.", binder.TempFilesLocation);
                    }
                }
            }

            return(this.messageHandler.LastErrorNumber);
        }
Exemplo n.º 4
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
            {
                XmlSchemaCollection objectSchema = new XmlSchemaCollection();
                FileInfo currentFile = null;

                ArrayList intermediates = new ArrayList();
                Linker linker = null;
                Microsoft.Tools.WindowsInstallerXml.Binder binder = null;
                Localizer localizer = null;

                try
                {
                    // parse the command line
                    this.ParseCommandLine(args);

                    // exit if there was an error parsing the command line (otherwise the logo appears after error messages)
                    if (this.messageHandler.FoundError)
                    {
                        return this.messageHandler.PostProcess();
                    }

                    if (0 == this.objectFiles.Count)
                    {
                        this.showHelp = true;
                    }
                    else if (null == this.outputFile)
                    {
                        if (1 < this.objectFiles.Count)
                        {
                            throw new ArgumentException("must specify output file when using more than one input file", "-out");
                        }

                        FileInfo fi = (FileInfo)this.objectFiles[0];
                        this.outputFile = new FileInfo(Path.ChangeExtension(fi.Name, ".wix"));   // we'll let the linker change the extension later
                    }

                    if (this.showLogo)
                    {
                        Assembly lightAssembly = Assembly.GetExecutingAssembly();

                        Console.WriteLine("Microsoft (R) Windows Installer Xml Linker version {0}", lightAssembly.GetName().Version.ToString());
                        Console.WriteLine("Copyright (C) Microsoft Corporation 2003. All rights reserved.");
                        Console.WriteLine();
                    }

                    if (this.showHelp)
                    {
                        Console.WriteLine(" usage:  light.exe [-?] [-b basePath] [-nologo] [-out outputFile] objectFile [objectFile ...]");
                        Console.WriteLine();
                        Console.WriteLine("   -ai        allow identical rows, identical rows will be treated as a warning");
                        Console.WriteLine("   -au        (experimental) allow unresolved references, will not create a valid output");
                        Console.WriteLine("   -b         base path to locate all files (default: current directory)");
                        Console.WriteLine("   -cc        path to cache built cabinets (will not be deleted after linking)");
                        Console.WriteLine("   -ext       extension (class, assembly), should extend SchemaExtension or BinderExtension");
                        Console.WriteLine("   -fv        add a 'fileVersion' entry to the MsiAssemblyName table (rarely needed)");
                        Console.WriteLine("   -i         specify the base output path for uncompressed images (default: -out parameter)");
                        Console.WriteLine("   -loc       read localization string sfrom .wxl file");
                        Console.WriteLine("   -nologo    skip printing light logo information");
                        Console.WriteLine("   -notidy    do not delete temporary files (useful for debugging)");
                        Console.WriteLine("   -reusecab  reuse cabinets from cabinet cache");
                        Console.WriteLine("   -out       specify output file (default: write to current directory)");
                        Console.WriteLine("   -xo        output xml instead of MSI format");
                        Console.WriteLine("   -pedantic:<level>  pedantic checks (levels: easy, heroic, legendary)");
                        Console.WriteLine("   -reusecab  reuse cabinets from cabinet cache");
                        Console.WriteLine("   -sa        suppress assemblies: do not get assembly name information for assemblies");
                        Console.WriteLine("   -sacl      suppress resetting ACLs (useful when laying out image to a network share)");
                        Console.WriteLine("   -sadmin    suppress default admin sequence actions");
                        Console.WriteLine("   -sadv      suppress default adv sequence actions");
                        Console.WriteLine("   -sa        suppress assemblys: do not get assembly name information for assemblies");
                        Console.WriteLine("   -sf        suppress files: do not get any file information (equivalent to -sa and -sh)");
                        Console.WriteLine("   -sh        suppress file info: do not get hash, version, language, etc");
                        Console.WriteLine("   -sl        suppress layout");
                        Console.WriteLine("   -ss        suppress schema validation of documents (performance boost)");
                        Console.WriteLine("   -sui       suppress default UI sequence actions");
                        Console.WriteLine("   -sv        suppress intermediate file version mismatch checking");
                        Console.WriteLine("   -ts        tag sectionId attribute on tuples (ignored if not used with -xo)");
                        Console.WriteLine("   -ust       use small table definitions (for backwards compatiblity)");
                        Console.WriteLine("   -wx        treat warnings as errors");
                        Console.WriteLine("   -w<N>      set the warning level (0: show all, 3: show none)");
                        Console.WriteLine("   -sw        suppress all warnings (same as -w3)");
                        Console.WriteLine("   -sw<N>     suppress warning with specific message ID");
                        Console.WriteLine("   -v         verbose output (same as -v2)");
                        Console.WriteLine("   -v<N>      sets the level of verbose output (0: most output, 3: none)");
                        Console.WriteLine("   -?         this help information");
                        Console.WriteLine();
                        Console.WriteLine("Environment variables:");
                        Console.WriteLine("   WIX_TEMP   overrides the temporary directory used for cab creation, msm exploding, ...");
                        Console.WriteLine();
                        Console.WriteLine("Common extensions:");
                        Console.WriteLine("   .wxs    - Windows installer Xml Source file");
                        Console.WriteLine("   .wxi    - Windows installer Xml Include file");
                        Console.WriteLine("   .wxl    - Windows installer Xml Localization file");
                        Console.WriteLine("   .wixobj - Windows installer Xml Object file (in XML format)");
                        Console.WriteLine("   .wixlib - Windows installer Xml Library file (in XML format)");
                        Console.WriteLine("   .wixout - Windows installer Xml Output file (in XML format)");
                        Console.WriteLine();
                        Console.WriteLine("   .msm - Windows installer Merge Module");
                        Console.WriteLine("   .msi - Windows installer Product Database");
                        Console.WriteLine("   .mst - Windows installer Transform");
                        Console.WriteLine("   .pcp - Windows installer Patch Creation Package");
                        Console.WriteLine();
                        Console.WriteLine("For more information see: http://wix.sourceforge.net");

                        return this.messageHandler.PostProcess();
                    }

                    // create the linker and the binder
                    linker = new Linker(this.useSmallTables);
                    binder = new Microsoft.Tools.WindowsInstallerXml.Binder(this.useSmallTables);

                    linker.AllowIdenticalRows = this.allowIdenticalRows;
                    linker.AllowUnresolvedReferences = this.allowUnresolvedReferences;
                    linker.PedanticLevel = this.pedanticLevel;

                    // set the sequence suppression options
                    linker.SuppressAdminSequence = this.suppressAdminSequence;
                    linker.SuppressAdvertiseSequence = this.suppressAdvertiseSequence;
                    linker.SuppressUISequence = this.suppressUISequence;

                    linker.SectionIdOnTuples = this.sectionIdOnTuples;
                    binder.SuppressAclReset = this.suppressAclReset;
                    binder.SetMsiAssemblyNameFileVersion = this.setMsiAssemblyNameFileVersion;
                    binder.SuppressAssemblies = this.suppressAssemblies;
                    binder.SuppressFileHashAndInfo = this.suppressFileHashAndInfo;

                    if (this.suppressFiles)
                    {
                        binder.SuppressAssemblies = true;
                        binder.SuppressFileHashAndInfo = true;
                    }

                    binder.SuppressLayout = this.suppressLayout;
                    binder.TempFilesLocation = Environment.GetEnvironmentVariable("WIX_TEMP");

                    if (null != this.cabCachePath || this.reuseCabinets)
                    {
                        // ensure the cabinet cache path exists if we are going to use it
                        if (null != this.cabCachePath && !Directory.Exists(this.cabCachePath))
                        {
                            Directory.CreateDirectory(this.cabCachePath);
                        }
                    }

                    if (null != this.basePaths)
                    {
                        foreach (string basePath in this.basePaths)
                        {
                            this.sourcePaths.Add(basePath);
                        }
                    }

                    // load any extensions
                    bool binderExtensionLoaded = false;
                    foreach (string extension in this.extensionList)
                    {
                        Type extensionType = Type.GetType(extension);
                        if (null == extensionType)
                        {
                            throw new WixInvalidExtensionException(extension);
                        }

                        if (extensionType.IsSubclassOf(typeof(BinderExtension)))
                        {
                            object[] extensionArgs = new object[] { this.basePaths, this.cabCachePath, this.reuseCabinets, this.sourcePaths };
                            BinderExtension binderExtension = Activator.CreateInstance(extensionType, extensionArgs) as BinderExtension;
                            Debug.Assert(null != binderExtension);
                            if (binderExtensionLoaded)
                            {
                                throw new ArgumentException(String.Format(CultureInfo.InvariantCulture, "cannot load binder extension: {0}.  light can only load one binder extension and has already loaded binder extension: {1}.", binderExtension.ToString(), binder.Extension.ToString()), "ext");
                            }

                            binder.Extension = binderExtension;
                            binderExtensionLoaded = true;
                        }
                        else if (extensionType.IsSubclassOf(typeof(SchemaExtension)))
                        {
                            linker.AddExtension((SchemaExtension)Activator.CreateInstance(extensionType));
                        }
                        else
                        {
                            throw new WixInvalidExtensionException(extension, extensionType, typeof(BinderExtension), typeof(SchemaExtension));
                        }
                    }

                    // if the binder extension has not been loaded yet use the built-in binder extension
                    if (!binderExtensionLoaded)
                    {
                        binder.Extension = new LightBinderExtension(this.basePaths, this.cabCachePath, this.reuseCabinets, this.sourcePaths);
                    }

                    if (null != this.imagebaseOutputPath)
                    {
                        binder.ImageBaseOutputPath = this.imagebaseOutputPath;
                    }

                    // set the message handlers
                    linker.Message += new MessageEventHandler(this.messageHandler.Display);
                    binder.Message += new MessageEventHandler(this.messageHandler.Display);

                    // load the object schema
                    if (!this.suppressSchema)
                    {
                        Assembly wixAssembly = Assembly.Load("wix");

                        using (Stream objectsSchemaStream = wixAssembly.GetManifestResourceStream("Microsoft.Tools.WindowsInstallerXml.Xsd.objects.xsd"))
                        {
                            XmlReader reader = new XmlTextReader(objectsSchemaStream);
                            objectSchema.Add("http://schemas.microsoft.com/wix/2003/04/objects", reader);
                        }
                    }

                    Output output = null;

                    // loop through all the believed object files
                    foreach (FileInfo objectFile in this.objectFiles)
                    {
                        currentFile = objectFile;
                        string dirName = Path.GetDirectoryName(currentFile.FullName);
                        if (!StringArrayContains(this.sourcePaths, dirName))
                        {
                            this.sourcePaths.Add(dirName);
                        }

                        // load the object file into an intermediate object and add it to the list to be linked
                        using (Stream fileStream = new FileStream(currentFile.FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                        {
                            XmlReader fileReader = new XmlTextReader(fileStream);

                            try
                            {
                                XmlReader intermediateReader = fileReader;
                                if (!this.suppressSchema)
                                {
                                    intermediateReader = new XmlValidatingReader(fileReader);
                                    ((XmlValidatingReader)intermediateReader).Schemas.Add(objectSchema);
                                }

                                Intermediate intermediate = Intermediate.Load(intermediateReader, currentFile.FullName, linker.TableDefinitions, this.suppressVersionCheck);
                                intermediates.Add(intermediate);
                                continue; // next file
                            }
                            catch (WixNotIntermediateException)
                            {
                                // try another format
                            }

                            try
                            {
                                Library library = Library.Load(currentFile.FullName, linker.TableDefinitions, this.suppressVersionCheck);
                                intermediates.AddRange(library.Intermediates);
                                continue; // next file
                            }
                            catch (WixNotLibraryException)
                            {
                                // try another format
                            }

                            output = Output.Load(currentFile.FullName, this.suppressVersionCheck);
                        }
                    }

                    // instantiate the localizer and load any wixloc files
                    if (0 < this.localizationFiles.Count || !this.outputXml)
                    {
                        localizer = new Localizer();

                        localizer.Message += new MessageEventHandler(this.messageHandler.Display);

                        // load each wixloc file
                        foreach (string localizationFile in this.localizationFiles)
                        {
                            localizer.LoadFromFile(localizationFile);
                        }

                        // immediately stop processing if any errors were found
                        if (this.messageHandler.FoundError)
                        {
                            return this.messageHandler.PostProcess();
                        }
                    }

                    // and now for the fun part
                    currentFile = this.outputFile;
                    if (null == output)
                    {
                        // tell the linker about the localizer
                        linker.Localizer = localizer;
                        localizer = null;

                        output = linker.Link((Intermediate[])intermediates.ToArray(typeof(Intermediate)));

                        // if an error occurred during linking, stop processing
                        if (null == output)
                        {
                            return this.messageHandler.PostProcess();
                        }
                    }
                    else if (0 != intermediates.Count)
                    {
                        throw new InvalidOperationException("Cannot link object files (.wixobj) files with an output file (.wixout)");
                    }

                    output.Path = this.outputFile.FullName;

                    // only output the xml
                    if (this.outputXml)
                    {
                        string outputExtension = Path.GetExtension(this.outputFile.FullName);
                        if (null == outputExtension || 0 == outputExtension.Length || ".wix" == outputExtension)
                        {
                            output.Path = Path.ChangeExtension(this.outputFile.FullName, ".wixout");
                        }
                        output.Save();
                    }
                    else // finish creating the MSI/MSM
                    {
                        string outputExtension = Path.GetExtension(this.outputFile.FullName);
                        if (null == outputExtension || 0 == outputExtension.Length || ".wix" == outputExtension)
                        {
                            if (OutputType.Module == output.Type)
                            {
                                output.Path = Path.ChangeExtension(this.outputFile.FullName, ".msm");
                            }
                            else if (OutputType.PatchCreation == output.Type)
                            {
                                output.Path = Path.ChangeExtension(this.outputFile.FullName, ".pcp");
                            }
                            else
                            {
                                output.Path = Path.ChangeExtension(this.outputFile.FullName, ".msi");
                            }
                        }

                        // tell the binder about the localizer
                        binder.Localizer = localizer;

                        binder.Bind(output);
                    }

                    currentFile = null;
                }
                catch (WixInvalidIdtException)
                {
                    this.tidy = false;   // make sure the IDT files stay around
                    throw;
                }
                catch (WixMergeFailureException)
                {
                    this.tidy = false; // make sure the merge.log stays around
                    throw;
                }
                finally
                {
                    if (null != binder)
                    {
                        if (this.tidy)
                        {
                            if (!binder.DeleteTempFiles())
                            {
                                Console.WriteLine("Warning, failed to delete temporary directory: {0}", binder.TempFilesLocation);
                            }
                        }
                        else
                        {
                            Console.WriteLine("Temporary directory located at '{0}'.", binder.TempFilesLocation);
                        }
                    }
                }
            }
            catch (WixException we)
            {
                // TODO: once all WixExceptions are converted to errors, this clause
                // should be a no-op that just catches WixFatalErrorException's
                this.messageHandler.Display("light.exe", "LGHT", we);
                return 1;
            }
            catch (Exception e)
            {
                this.OnMessage(WixErrors.UnexpectedException(e.Message, e.GetType().ToString(), e.StackTrace));
                if (e is NullReferenceException || e is SEHException)
                {
                    throw;
                }
            }

            return this.messageHandler.PostProcess();
        }
Exemplo n.º 5
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)
        {
            Microsoft.Tools.WindowsInstallerXml.Binder binder = null;
            Differ differ = null;
            Unbinder unbinder = null;

            TempFileCollection tempFileCollection = null;

            try
            {
                // parse the command line
                this.ParseCommandLine(args);

                // validate the inputs
                if (this.xmlInputs && this.adminImage)
                {
                    this.messageHandler.Display(this, WixErrors.IllegalCommandlineArgumentCombination("a", "xi"));
                    this.showHelp = true;
                }

                string[] allValidExtensions = new string[] { wixMstExtension, wixOutExtension, wixPdbExtension, msiExtension };
                string[] expectedSingleInputExtensions = new string[] { wixMstExtension, wixOutExtension };
                string[] expectedDoubleInputXmlExtensions = new string[] { wixOutExtension, wixPdbExtension };
                string[] expectedDoubleInputMsiExtensions = new string[] { msiExtension };

                // Validate that all inputs have the correct extension and we dont have too many inputs.
                if (1 == this.inputFiles.Count)
                {
                    string inputFile = this.inputFiles[0];

                    bool hasValidExtension = false;
                    foreach (string extension in expectedSingleInputExtensions)
                    {
                        if (String.Equals(Path.GetExtension(inputFile), extension, StringComparison.OrdinalIgnoreCase))
                        {
                            hasValidExtension = true;
                            break;
                        }
                    }

                    if (!hasValidExtension)
                    {
                        bool missingInput = false;

                        // Check if its using an extension that could be valid in other scenarios.
                        foreach (string validExtension in allValidExtensions)
                        {
                            if (String.Equals(Path.GetExtension(inputFile), validExtension, StringComparison.OrdinalIgnoreCase))
                            {
                                this.messageHandler.Display(this, WixErrors.WrongFileExtensionForNumberOfInputs(Path.GetExtension(inputFile), inputFile));
                                missingInput = true;
                                break;
                            }
                        }

                        if (!missingInput)
                        {
                            this.messageHandler.Display(this, WixErrors.UnexpectedFileExtension(inputFile, String.Join(", ", expectedSingleInputExtensions)));
                        }
                    }
                }
                else if (2 == this.inputFiles.Count)
                {
                    foreach (string inputFile in inputFiles)
                    {
                        bool hasValidExtension = false;
                        string[] expectedExtensions = allValidExtensions;
                        if (this.xmlInputs)
                        {
                            foreach (string extension in expectedDoubleInputXmlExtensions)
                            {
                                if (String.Equals(Path.GetExtension(inputFile), extension, StringComparison.OrdinalIgnoreCase))
                                {
                                    hasValidExtension = true;
                                    expectedExtensions = expectedDoubleInputXmlExtensions;
                                    break;
                                }
                            }
                        }
                        else
                        {
                            foreach (string extension in expectedDoubleInputMsiExtensions)
                            {
                                if (String.Equals(Path.GetExtension(inputFile), extension, StringComparison.OrdinalIgnoreCase))
                                {
                                    hasValidExtension = true;
                                    expectedExtensions = expectedDoubleInputMsiExtensions;
                                    break;
                                }
                            }
                        }

                        if (!hasValidExtension)
                        {
                            this.messageHandler.Display(this, WixErrors.UnexpectedFileExtension(inputFile, String.Join(", ", expectedExtensions)));
                        }
                    }
                }
                else
                {
                    this.showHelp = true;
                }

                // exit if there was an error parsing the command line or with a file extension (otherwise the logo appears after error messages)
                if (this.messageHandler.EncounteredError)
                {
                    return this.messageHandler.LastErrorNumber;
                }

                if (null == this.outputFile)
                {
                    this.showHelp = true;
                }

                if (this.showLogo)
                {
                    AppCommon.DisplayToolHeader();
                }

                if (this.showHelp)
                {
                    Console.WriteLine(TorchStrings.HelpMessage);
                    AppCommon.DisplayToolFooter();
                    return this.messageHandler.LastErrorNumber;
                }

                foreach (string parameter in this.invalidArgs)
                {
                    this.messageHandler.Display(this, WixWarnings.UnsupportedCommandLineArgument(parameter));
                }
                this.invalidArgs = null;

                binder = new Microsoft.Tools.WindowsInstallerXml.Binder();
                differ = new Differ();
                unbinder = new Unbinder();

                // load any extensions
                foreach (string extension in this.extensionList)
                {
                    WixExtension wixExtension = WixExtension.Load(extension);
                    unbinder.AddExtension(wixExtension);
                    binder.AddExtension(wixExtension);
                    differ.AddExtension(wixExtension);
                }

                binder.Message += new MessageEventHandler(this.messageHandler.Display);
                differ.Message += new MessageEventHandler(this.messageHandler.Display);
                unbinder.Message += new MessageEventHandler(this.messageHandler.Display);

                binder.TempFilesLocation = Environment.GetEnvironmentVariable("WIX_TEMP");
                unbinder.TempFilesLocation = Environment.GetEnvironmentVariable("WIX_TEMP");
                tempFileCollection = new TempFileCollection(Environment.GetEnvironmentVariable("WIX_TEMP"));

                binder.WixVariableResolver = new WixVariableResolver();
                differ.PreserveUnchangedRows = this.preserveUnchangedRows;
                differ.ShowPedanticMessages = this.showPedanticMessages;
                unbinder.SuppressExtractCabinets = true;
                unbinder.IsAdminImage = this.adminImage;

                if (null == this.exportBasePath)
                {
                    this.exportBasePath = tempFileCollection.BasePath;
                }

                // load and process the inputs
                Output transform;
                if (1 == this.inputFiles.Count)
                {
                    transform = Output.Load(this.inputFiles[0], false, false);
                    if (OutputType.Transform != transform.Type)
                    {
                        this.messageHandler.Display(this, WixErrors.InvalidWixTransform(this.inputFiles[0]));
                        return this.messageHandler.LastErrorNumber;
                    }
                }
                else // 2 inputs
                {
                    Output targetOutput;
                    Output updatedOutput;

                    if (this.xmlInputs)
                    {
                        // load the target database
                        if (String.Equals(Path.GetExtension(inputFiles[0]), wixPdbExtension, StringComparison.OrdinalIgnoreCase))
                        {
                            Pdb targetPdb = Pdb.Load(this.inputFiles[0], false, false);
                            targetOutput = targetPdb.Output;
                        }
                        else
                        {
                            targetOutput = Output.Load(this.inputFiles[0], false, false);
                        }

                        // load the updated database
                        if (String.Equals(Path.GetExtension(inputFiles[1]), wixPdbExtension, StringComparison.OrdinalIgnoreCase))
                        {
                            Pdb updatedPdb = Pdb.Load(this.inputFiles[1], false, false);
                            updatedOutput = updatedPdb.Output;
                        }
                        else
                        {
                            updatedOutput = Output.Load(this.inputFiles[1], false, false);
                        }

                        this.xmlOutput = true;
                    }
                    else
                    {
                        // load the target database
                        targetOutput = unbinder.Unbind(this.inputFiles[0], OutputType.Product, Path.Combine(this.exportBasePath, "targetBinaries"));

                        // load the updated database
                        updatedOutput = unbinder.Unbind(this.inputFiles[1], OutputType.Product, Path.Combine(this.exportBasePath, "updatedBinaries"));
                    }

                    // diff the target and updated databases
                    transform = differ.Diff(targetOutput, updatedOutput, this.validationFlags);

                    if (null == transform.Tables || 0 >= transform.Tables.Count)
                    {
                        throw new WixException(WixErrors.NoDifferencesInTransform(transform.SourceLineNumbers));
                    }
                }

                // output the transform
                if (null != transform)
                {
                    // If either the user selected xml output or gave xml input, save as xml output.
                    // With xml inputs, many funtions of the binder have not been performed on the inputs (ie. file sequencing). This results in bad IDT files which cannot be put in a transform.
                    if (this.xmlOutput)
                    {
                        transform.Save(this.outputFile, null, null, tempFileCollection.BasePath);
                    }
                    else
                    {
                        binder.Bind(transform, this.outputFile);
                    }
                }
            }
            catch (WixException we)
            {
                if (we is WixInvalidIdtException)
                {
                    // make sure the IDT files stay around
                    this.tidy = false;
                }

                this.messageHandler.Display(this, we.Error);
            }
            catch (Exception e)
            {
                // make sure the files stay around for debugging
                this.tidy = false;

                this.messageHandler.Display(this, WixErrors.UnexpectedException(e.Message, e.GetType().ToString(), e.StackTrace));
                if (e is NullReferenceException || e is SEHException)
                {
                    throw;
                }
            }
            finally
            {
                if (null != binder)
                {
                    if (this.tidy)
                    {
                        if (!binder.DeleteTempFiles())
                        {
                            Console.WriteLine(TorchStrings.WAR_FailedToDeleteTempDir, binder.TempFilesLocation);
                        }
                    }
                    else
                    {
                        Console.WriteLine(TorchStrings.INF_BinderTempDirLocatedAt, binder.TempFilesLocation);
                    }
                }

                if (null != unbinder)
                {
                    if (this.tidy)
                    {
                        if (!unbinder.DeleteTempFiles())
                        {
                            Console.WriteLine(TorchStrings.WAR_FailedToDeleteTempDir, binder.TempFilesLocation);
                        }
                    }
                    else
                    {
                        Console.WriteLine(TorchStrings.INF_UnbinderTempDirLocatedAt, binder.TempFilesLocation);
                    }
                }

                if (null != tempFileCollection)
                {
                    if (this.tidy)
                    {
                        try
                        {
                            Directory.Delete(tempFileCollection.BasePath, true);
                        }
                        catch (DirectoryNotFoundException)
                        {
                            // if the path doesn't exist, then there is nothing for us to worry about
                        }
                        catch
                        {
                            Console.WriteLine(TorchStrings.WAR_FailedToDeleteTempDir, tempFileCollection.BasePath);
                        }
                    }
                    else
                    {
                        Console.WriteLine(TorchStrings.INF_TorchTempDirLocatedAt, tempFileCollection.BasePath);
                    }
                }
            }

            return this.messageHandler.LastErrorNumber;
        }
Exemplo n.º 6
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 (null == this.inputFile || null == this.outputFile)
                {
                    this.showHelp = true;
                }

                if (this.showLogo)
                {
                    AppCommon.DisplayToolHeader();
                }

                if (this.showHelp)
                {
                    Console.WriteLine(PyroStrings.HelpMessage);
                    AppCommon.DisplayToolFooter();
                    return(this.messageHandler.LastErrorNumber);
                }

                // Load in transforms
                ArrayList transforms = new ArrayList();
                foreach (string inputTransform in inputTransformsOrdered)
                {
                    PatchTransform patchTransform = new PatchTransform(inputTransform, inputTransforms[inputTransform]);
                    patchTransform.Message += new MessageEventHandler(this.messageHandler.Display);
                    transforms.Add(patchTransform);
                }

                // Create and configure the patch
                Patch patch = new Patch();
                patch.Message += new MessageEventHandler(this.messageHandler.Display);

                // Create and configure the binder
                binder = new Microsoft.Tools.WindowsInstallerXml.Binder();
                binder.TempFilesLocation             = Environment.GetEnvironmentVariable("WIX_TEMP");
                binder.WixVariableResolver           = this.wixVariableResolver;
                binder.Message                      += new MessageEventHandler(this.messageHandler.Display);
                binder.SuppressAssemblies            = this.suppressAssemblies;
                binder.SuppressFileHashAndInfo       = this.suppressFileHashAndInfo;
                binder.SetMsiAssemblyNameFileVersion = this.setAssemblyFileVersions;

                // have the binder parse the command line arguments light did not recognize
                string[] unparsedArgsArray = new string[this.unparsedArgs.Count];
                this.unparsedArgs.CopyTo(unparsedArgsArray, 0);
                StringCollection remainingArgs = this.binder.ParseCommandLine(unparsedArgsArray, this.messageHandler);

                // Load the extensions
                bool binderFileManagerLoaded = false;
                foreach (String extension in this.extensions)
                {
                    WixExtension wixExtension = WixExtension.Load(extension);
                    binder.AddExtension(wixExtension);
                    patch.AddExtension(wixExtension);

                    if (0 < remainingArgs.Count)
                    {
                        remainingArgs = wixExtension.ParseCommandLine(remainingArgs, this.messageHandler);
                    }

                    if (null != wixExtension.BinderFileManager)
                    {
                        if (binderFileManagerLoaded)
                        {
                            throw new ArgumentException(String.Format(CultureInfo.CurrentUICulture, PyroStrings.EXP_CannotLoadBinderFileManager, wixExtension.BinderFileManager.GetType().ToString(), binder.FileManager.ToString()), "ext");
                        }

                        binder.FileManager      = wixExtension.BinderFileManager;
                        binderFileManagerLoaded = true;
                    }
                }

                foreach (string parameter in remainingArgs)
                {
                    this.messageHandler.Display(this, WixWarnings.UnsupportedCommandLineArgument(parameter));
                }

                if (this.messageHandler.EncounteredError)
                {
                    return(this.messageHandler.LastErrorNumber);
                }

                // since the binder is now ready, let's plug dynamic bindpath into file manager
                this.PrepareDataForFileManager();

                // Load the patch
                patch.Load(this.inputFile);

                // Copy transforms into output
                if (0 < transforms.Count)
                {
                    patch.AttachTransforms(transforms);
                }

                if (this.messageHandler.EncounteredError)
                {
                    return(this.messageHandler.LastErrorNumber);
                }

                if (null == this.pdbFile && null != this.outputFile)
                {
                    this.pdbFile = Path.ChangeExtension(this.outputFile, ".wixpdb");
                }

                binder.PdbFile = suppressWixPdb ? null : this.pdbFile;

                if (this.suppressFiles)
                {
                    binder.SuppressAssemblies      = true;
                    binder.SuppressFileHashAndInfo = true;
                }

                if (null != this.cabCachePath || this.reuseCabinets)
                {
                    // ensure the cabinet cache path exists if we are going to use it
                    if (null != this.cabCachePath && !Directory.Exists(this.cabCachePath))
                    {
                        Directory.CreateDirectory(this.cabCachePath);
                    }
                }

                binder.AllowEmptyTransforms = this.allowEmptyTransforms;

                binder.FileManager.ReuseCabinets    = this.reuseCabinets;
                binder.FileManager.CabCachePath     = this.cabCachePath;
                binder.FileManager.Output           = patch.PatchOutput;
                binder.FileManager.DeltaBinaryPatch = this.delta;

                // Bind the patch to an msp.
                binder.Bind(patch.PatchOutput, this.outputFile);
            }
            catch (WixException we)
            {
                this.OnMessage(we.Error);
            }
            catch (Exception e)
            {
                this.OnMessage(WixErrors.UnexpectedException(e.Message, e.GetType().ToString(), e.StackTrace));
                if (e is NullReferenceException || e is SEHException)
                {
                    throw;
                }
            }
            finally
            {
                if (null != binder)
                {
                    if (this.tidy)
                    {
                        if (!binder.DeleteTempFiles())
                        {
                            Console.WriteLine(PyroStrings.WAR_FailedToDeleteTempDir, binder.TempFilesLocation);
                        }
                    }
                    else
                    {
                        Console.WriteLine(PyroStrings.INF_TempDirLocatedAt, binder.TempFilesLocation);
                    }
                }
            }

            return(this.messageHandler.LastErrorNumber);
        }
Exemplo n.º 7
0
Arquivo: pyro.cs Projeto: zooba/wix3
        /// <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 (null == this.inputFile || null == this.outputFile)
                {
                    this.showHelp = true;
                }

                if (this.showLogo)
                {
                    AppCommon.DisplayToolHeader();
                }

                if (this.showHelp)
                {
                    Console.WriteLine(PyroStrings.HelpMessage);
                    AppCommon.DisplayToolFooter();
                    return this.messageHandler.LastErrorNumber;
                }

                // Load in transforms
                ArrayList transforms = new ArrayList();
                foreach (string inputTransform in inputTransformsOrdered)
                {
                    PatchTransform patchTransform = new PatchTransform(inputTransform, inputTransforms[inputTransform]);
                    patchTransform.Message += new MessageEventHandler(this.messageHandler.Display);
                    transforms.Add(patchTransform);
                }

                // Create and configure the patch
                Patch patch = new Patch();
                patch.Message += new MessageEventHandler(this.messageHandler.Display);

                // Create and configure the binder
                binder = new Microsoft.Tools.WindowsInstallerXml.Binder();
                binder.TempFilesLocation = Environment.GetEnvironmentVariable("WIX_TEMP");
                binder.WixVariableResolver = this.wixVariableResolver;
                binder.Message += new MessageEventHandler(this.messageHandler.Display);
                binder.SuppressAssemblies = this.suppressAssemblies;
                binder.SuppressFileHashAndInfo = this.suppressFileHashAndInfo;
                binder.SetMsiAssemblyNameFileVersion = this.setAssemblyFileVersions;

                // have the binder parse the command line arguments light did not recognize
                string[] unparsedArgsArray = new string[this.unparsedArgs.Count];
                this.unparsedArgs.CopyTo(unparsedArgsArray, 0);
                StringCollection remainingArgs = this.binder.ParseCommandLine(unparsedArgsArray, this.messageHandler);

                // Load the extensions
                bool binderFileManagerLoaded = false;
                foreach (String extension in this.extensions)
                {
                    WixExtension wixExtension = WixExtension.Load(extension);
                    binder.AddExtension(wixExtension);
                    patch.AddExtension(wixExtension);

                    if (0 < remainingArgs.Count)
                    {
                        remainingArgs = wixExtension.ParseCommandLine(remainingArgs, this.messageHandler);
                    }

                    if (null != wixExtension.BinderFileManager)
                    {
                        if (binderFileManagerLoaded)
                        {
                            throw new ArgumentException(String.Format(CultureInfo.CurrentUICulture, PyroStrings.EXP_CannotLoadBinderFileManager, wixExtension.BinderFileManager.GetType().ToString(), binder.FileManager.ToString()), "ext");
                        }

                        binder.FileManager = wixExtension.BinderFileManager;
                        binderFileManagerLoaded = true;
                    }
                }

                foreach (string parameter in remainingArgs)
                {
                    this.messageHandler.Display(this, WixWarnings.UnsupportedCommandLineArgument(parameter));
                }

                if (this.messageHandler.EncounteredError)
                {
                    return this.messageHandler.LastErrorNumber;
                }

                // since the binder is now ready, let's plug dynamic bindpath into file manager
                this.PrepareDataForFileManager();

                // Load the patch
                patch.Load(this.inputFile);

                // Copy transforms into output
                if (0 < transforms.Count)
                {
                    patch.AttachTransforms(transforms);
                }

                if (this.messageHandler.EncounteredError)
                {
                    return this.messageHandler.LastErrorNumber;
                }

                if (null == this.pdbFile && null != this.outputFile)
                {
                    this.pdbFile = Path.ChangeExtension(this.outputFile, ".wixpdb");
                }

                binder.PdbFile = suppressWixPdb ? null : this.pdbFile;

                if (this.suppressFiles)
                {
                    binder.SuppressAssemblies = true;
                    binder.SuppressFileHashAndInfo = true;
                }

                if (null != this.cabCachePath || this.reuseCabinets)
                {
                    // ensure the cabinet cache path exists if we are going to use it
                    if (null != this.cabCachePath && !Directory.Exists(this.cabCachePath))
                    {
                        Directory.CreateDirectory(this.cabCachePath);
                    }
                }

                binder.AllowEmptyTransforms = this.allowEmptyTransforms;

                binder.FileManager.ReuseCabinets = this.reuseCabinets;
                binder.FileManager.CabCachePath = this.cabCachePath;
                binder.FileManager.Output = patch.PatchOutput;
                binder.FileManager.DeltaBinaryPatch = this.delta;

                // Bind the patch to an msp.
                binder.Bind(patch.PatchOutput, this.outputFile);
            }
            catch (WixException we)
            {
                this.OnMessage(we.Error);
            }
            catch (Exception e)
            {
                this.OnMessage(WixErrors.UnexpectedException(e.Message, e.GetType().ToString(), e.StackTrace));
                if (e is NullReferenceException || e is SEHException)
                {
                    throw;
                }
            }
            finally
            {
                if (null != binder)
                {
                    if (this.tidy)
                    {
                        if (!binder.DeleteTempFiles())
                        {
                            Console.WriteLine(PyroStrings.WAR_FailedToDeleteTempDir, binder.TempFilesLocation);
                        }
                    }
                    else
                    {
                        Console.WriteLine(PyroStrings.INF_TempDirLocatedAt, binder.TempFilesLocation);
                    }
                }
            }

            return this.messageHandler.LastErrorNumber;
        }
Exemplo n.º 8
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)
        {
            Microsoft.Tools.WindowsInstallerXml.Binder binder = null;
            Differ   differ   = null;
            Unbinder unbinder = null;

            TempFileCollection tempFileCollection = null;

            try
            {
                // parse the command line
                this.ParseCommandLine(args);

                // exit if there was an error parsing the command line (otherwise the logo appears after error messages)
                if (this.messageHandler.EncounteredError)
                {
                    return(this.messageHandler.LastErrorNumber);
                }

                // validate the inputs
                if (1 == this.inputFiles.Count)
                {
                    // Validate that if its a single input, it is a wixout to be converted to an mst.
                    if (0 != String.Compare(Path.GetExtension(this.inputFiles[0]), ".wixout", true, CultureInfo.InvariantCulture))
                    {
                        this.showHelp = true;
                    }
                }
                else if (2 == this.inputFiles.Count)
                {
                    string expectedExtension = ".msi";
                    if (this.xmlInputs)
                    {
                        expectedExtension = ".wixout";
                    }

                    // Validate that all inputs have the correct extension
                    foreach (string inputFile in inputFiles)
                    {
                        if (0 != String.Compare(Path.GetExtension(inputFile), expectedExtension, true, CultureInfo.InvariantCulture))
                        {
                            this.messageHandler.Display(this, WixErrors.UnexpectedFileExtension(this.inputFiles[0], expectedExtension));
                            this.showHelp = true;
                        }
                    }
                }
                else
                {
                    this.showHelp = true;
                }

                if (null == this.outputFile)
                {
                    this.showHelp = true;
                }

                if (this.showLogo)
                {
                    Assembly torchAssembly = Assembly.GetExecutingAssembly();

                    Console.WriteLine("Microsoft (R) Windows Installer Xml Transform Builder Version {0}", torchAssembly.GetName().Version.ToString());
                    Console.WriteLine("Copyright (C) Microsoft Corporation 2003. All rights reserved.\n");
                    Console.WriteLine();
                }

                if (this.showHelp)
                {
                    Console.WriteLine(" usage: torch.exe [-?] [options] targetInput updatedInput -out outputFile");
                    Console.WriteLine();
                    Console.WriteLine("   -nologo    skip printing logo information");
                    Console.WriteLine("   -notidy    do not delete temporary files (useful for debugging)");
                    Console.WriteLine("   -p         preserve unmodified content in the output");
                    Console.WriteLine("   -sw<N>     suppress warning with specific message ID");
                    Console.WriteLine("   -v         verbose output");
                    Console.WriteLine("   -wx        treat warnings as errors");
                    Console.WriteLine("   -xi        input xml instead of MSI format");
                    Console.WriteLine("   -xo        output xml instead of MST format (set by default if -xi is present");
                    Console.WriteLine("   -?         this help information");
                    Console.WriteLine();
                    Console.WriteLine("Environment variables:");
                    Console.WriteLine("   WIX_TEMP   overrides the temporary directory used for cab extraction, binary extraction, ...");
                    Console.WriteLine();
                    Console.WriteLine("Common extensions:");
                    Console.WriteLine("   .wxi    - Windows installer Xml Include file");
                    Console.WriteLine("   .wxl    - Windows installer Xml Localization file");
                    Console.WriteLine("   .wxs    - Windows installer Xml Source file");
                    Console.WriteLine("   .wixlib - Windows installer Xml Library file (in XML format)");
                    Console.WriteLine("   .wixobj - Windows installer Xml Object file (in XML format)");
                    Console.WriteLine("   .wixout - Windows installer Xml Output file (in XML format)");
                    Console.WriteLine();
                    Console.WriteLine("   .msi - Windows installer Product Database");
                    Console.WriteLine("   .msm - Windows installer Merge Module");
                    Console.WriteLine("   .msp - Windows installer Patch");
                    Console.WriteLine("   .mst - Windows installer Transform");
                    Console.WriteLine("   .pcp - Windows installer Patch Creation Package");
                    Console.WriteLine();
                    Console.WriteLine("For more information see: http://wix.sourceforge.net");

                    return(this.messageHandler.LastErrorNumber);
                }

                binder   = new Microsoft.Tools.WindowsInstallerXml.Binder();
                differ   = new Differ();
                unbinder = new Unbinder();

                binder.Message   += new MessageEventHandler(this.messageHandler.Display);
                differ.Message   += new MessageEventHandler(this.messageHandler.Display);
                unbinder.Message += new MessageEventHandler(this.messageHandler.Display);

                binder.TempFilesLocation   = Environment.GetEnvironmentVariable("WIX_TEMP");
                unbinder.TempFilesLocation = Environment.GetEnvironmentVariable("WIX_TEMP");
                tempFileCollection         = new TempFileCollection(Environment.GetEnvironmentVariable("WIX_TEMP"));

                binder.WixVariableResolver       = new WixVariableResolver();
                differ.PreserveUnchangedRows     = this.preserveUnchangedRows;
                unbinder.SuppressExtractCabinets = true;

                // load and process the inputs
                Output transform;
                if (1 == this.inputFiles.Count)
                {
                    transform = Output.Load(this.inputFiles[0], false, false);
                    if (OutputType.Transform != transform.Type)
                    {
                        this.messageHandler.Display(this, WixErrors.InvalidWixTransform(this.inputFiles[0]));
                        return(this.messageHandler.LastErrorNumber);
                    }
                }
                else // 2 inputs
                {
                    Output targetOutput;
                    Output updatedOutput;

                    if (this.xmlInputs)
                    {
                        // load the target database
                        targetOutput = Output.Load(this.inputFiles[0], false, false);

                        // load the updated database
                        updatedOutput = Output.Load(this.inputFiles[1], false, false);
                    }
                    else
                    {
                        // load the target database
                        targetOutput = unbinder.Unbind(this.inputFiles[0], OutputType.Product, Path.Combine(tempFileCollection.BasePath, "targetBinaries"));

                        // load the updated database
                        updatedOutput = unbinder.Unbind(this.inputFiles[1], OutputType.Product, Path.Combine(tempFileCollection.BasePath, "updatedBinaries"));
                    }

                    // diff the target and updated databases
                    transform = differ.Diff(targetOutput, updatedOutput);

                    if (null == transform.Tables || 0 >= transform.Tables.Count)
                    {
                        throw new WixException(WixErrors.NoDifferencesInTransform(transform.SourceLineNumbers));
                    }
                }

                // output the transform
                if (null != transform)
                {
                    // If either the user selected xml output or gave xml input, save as xml output.
                    // With xml inputs, many funtions of the binder have not been performed on the inputs (ie. file sequencing). This results in bad IDT files which cannot be put in a transform.
                    if (this.xmlOutput || this.xmlInputs)
                    {
                        transform.Save(this.outputFile, null, null, null);
                    }
                    else
                    {
                        binder.Bind(transform, this.outputFile);
                    }
                }
            }
            catch (WixException we)
            {
                if (we is WixInvalidIdtException)
                {
                    // make sure the IDT files stay around
                    this.tidy = false;
                }

                this.messageHandler.Display(this, we.Error);
            }
            catch (Exception e)
            {
                // make sure the files stay around for debugging
                this.tidy = false;

                this.messageHandler.Display(this, WixErrors.UnexpectedException(e.Message, e.GetType().ToString(), e.StackTrace));
                if (e is NullReferenceException || e is SEHException)
                {
                    throw;
                }
            }
            finally
            {
                if (null != binder)
                {
                    if (this.tidy)
                    {
                        if (!binder.DeleteTempFiles())
                        {
                            Console.WriteLine("Warning, failed to delete temporary directory: {0}", binder.TempFilesLocation);
                        }
                    }
                    else
                    {
                        Console.WriteLine("Binder temporary directory located at '{0}'.", binder.TempFilesLocation);
                    }
                }

                if (null != unbinder)
                {
                    if (this.tidy)
                    {
                        if (!unbinder.DeleteTempFiles())
                        {
                            Console.WriteLine("Warning, failed to delete temporary directory: {0}", binder.TempFilesLocation);
                        }
                    }
                    else
                    {
                        Console.WriteLine("Unbinder temporary directory located at '{0}'.", binder.TempFilesLocation);
                    }
                }

                if (null != tempFileCollection)
                {
                    if (this.tidy)
                    {
                        try
                        {
                            Directory.Delete(tempFileCollection.BasePath, true);
                        }
                        catch
                        {
                            Console.WriteLine("Warning, failed to delete temporary directory: {0}", tempFileCollection.BasePath);
                        }
                    }
                    else
                    {
                        Console.WriteLine("Torch temporary directory located at '{0}'.", tempFileCollection.BasePath);
                    }
                }
            }

            return(this.messageHandler.LastErrorNumber);
        }
Exemplo n.º 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)
        {
            Microsoft.Tools.WindowsInstallerXml.Binder binder = null;
            Linker            linker     = null;
            Localizer         localizer  = null;
            SectionCollection sections   = new SectionCollection();
            ArrayList         transforms = new ArrayList();

            try
            {
                // parse the command line
                this.ParseCommandLine(args);

                // exit if there was an error parsing the command line (otherwise the logo appears after error messages)
                if (this.messageHandler.EncounteredError)
                {
                    return(this.messageHandler.LastErrorNumber);
                }

                if (0 == this.inputFiles.Count)
                {
                    this.showHelp = true;
                }
                else if (null == this.outputFile)
                {
                    if (1 < this.inputFiles.Count)
                    {
                        throw new ArgumentException("must specify output file when using more than one input file", "-out");
                    }

                    this.outputFile = Path.ChangeExtension(Path.GetFileName(this.inputFiles[0]), ".wix"); // we'll let the linker change the extension later
                }

                if (this.showLogo)
                {
                    Assembly lightAssembly = Assembly.GetExecutingAssembly();

                    Console.WriteLine("Microsoft (R) Windows Installer Xml Linker version {0}", lightAssembly.GetName().Version.ToString());
                    Console.WriteLine("Copyright (C) Microsoft Corporation 2003. All rights reserved.");
                    Console.WriteLine();
                }

                if (this.showHelp)
                {
                    Console.WriteLine(" usage:  light.exe [-?] [-b basePath] [-nologo] [-out outputFile] objectFile [objectFile ...]");
                    Console.WriteLine();
                    Console.WriteLine("   -ai        allow identical rows, identical rows will be treated as a warning");
                    Console.WriteLine("   -au        (experimental) allow unresolved references, will not create a valid output");
                    Console.WriteLine("   -b         base path to locate all files (default: current directory)");
                    Console.WriteLine("   -bf        bind files into a wixout (only valid with -xo option)");
                    Console.WriteLine("   -cc        path to cache built cabinets (will not be deleted after linking)");
                    Console.WriteLine("   -ct <N>    number of threads to use when creating cabinets (default: %NUMBER_OF_PROCESSORS%)");
                    Console.WriteLine("   -cultures:<cultures>  semicolon-delimited list of localized string cultures to load from libraries");
                    Console.WriteLine("   -cub       additional .cub file containing ICEs to run");
                    Console.WriteLine("   -d<name>=<value>  define a wix variable");
                    Console.WriteLine("   -ext       extension assembly or \"class, assembly\"");
                    Console.WriteLine("   -fv        add a 'fileVersion' entry to the MsiAssemblyName table (rarely needed)");
                    Console.WriteLine("   -loc <loc.wxl>  read localization strings from .wxl file");
                    Console.WriteLine("   -nologo    skip printing light logo information");
                    Console.WriteLine("   -notidy    do not delete temporary files (useful for debugging)");
                    Console.WriteLine("   -out       specify output file (default: write to current directory)");
                    Console.WriteLine("   -pedantic  show pedantic messages");
                    Console.WriteLine("   -reusecab  reuse cabinets from cabinet cache");
                    Console.WriteLine("   -sa        suppress assemblies: do not get assembly name information for assemblies");
                    Console.WriteLine("   -sacl      suppress resetting ACLs (useful when laying out image to a network share)");
                    Console.WriteLine("   -sadmin    suppress default admin sequence actions");
                    Console.WriteLine("   -sadv      suppress default adv sequence actions");
                    Console.WriteLine("   -sdut      suppress dropping unreal tables to the output image (default with -xo)");
                    Console.WriteLine("   -sice:<ICE>  suppress an internal consistency evaluator (ICE)");
                    Console.WriteLine("   -sma       suppress processing the data in MsiAssembly table");
                    Console.WriteLine("   -sf        suppress files: do not get any file information (equivalent to -sa and -sh)");
                    Console.WriteLine("   -sh        suppress file info: do not get hash, version, language, etc");
                    Console.WriteLine("   -sl        suppress layout");
                    Console.WriteLine("   -ss        suppress schema validation of documents (performance boost)");
                    Console.WriteLine("   -sui       suppress default UI sequence actions");
                    Console.WriteLine("   -sv        suppress intermediate file version mismatch checking");
                    Console.WriteLine("   -sval      suppress MSI/MSM validation");
                    Console.WriteLine("   -sw<N>     suppress warning with specific message ID");
                    Console.WriteLine("   -ts        tag sectionId attribute on rows (default with -xo)");
                    Console.WriteLine("   -tsa       tag sectionId attribute on rows, generating when null (default with -xo)");
                    Console.WriteLine("   -usf <output.xml>  unreferenced symbols file");
                    Console.WriteLine("   -v         verbose output");
                    Console.WriteLine("   -wx        treat warnings as errors");
                    Console.WriteLine("   -xo        output xml instead of MSI format");
                    Console.WriteLine("   -?         this help information");
                    Console.WriteLine();
                    Console.WriteLine("Environment variables:");
                    Console.WriteLine("   WIX_TEMP   overrides the temporary directory used for cab creation, msm exploding, ...");
                    Console.WriteLine();
                    Console.WriteLine("Common extensions:");
                    Console.WriteLine("   .wxi    - Windows installer Xml Include file");
                    Console.WriteLine("   .wxl    - Windows installer Xml Localization file");
                    Console.WriteLine("   .wxs    - Windows installer Xml Source file");
                    Console.WriteLine("   .wixlib - Windows installer Xml Library file (in XML format)");
                    Console.WriteLine("   .wixobj - Windows installer Xml Object file (in XML format)");
                    Console.WriteLine("   .wixout - Windows installer Xml Output file (in XML format)");
                    Console.WriteLine();
                    Console.WriteLine("   .msi - Windows installer Product Database");
                    Console.WriteLine("   .msm - Windows installer Merge Module");
                    Console.WriteLine("   .msp - Windows installer Patch");
                    Console.WriteLine("   .mst - Windows installer Transform");
                    Console.WriteLine("   .pcp - Windows installer Patch Creation Package");
                    Console.WriteLine();
                    Console.WriteLine("For more information see: http://wix.sourceforge.net");

                    return(this.messageHandler.LastErrorNumber);
                }

                // create the linker, binder, and validator
                linker = new Linker();
                binder = new Microsoft.Tools.WindowsInstallerXml.Binder();

                linker.AllowIdenticalRows        = this.allowIdenticalRows;
                linker.AllowUnresolvedReferences = this.allowUnresolvedReferences;
                linker.Cultures = this.cultures;
                linker.UnreferencedSymbolsFile      = this.unreferencedSymbolsFile;
                linker.ShowPedanticMessages         = this.showPedanticMessages;
                linker.SuppressDroppingUnrealTables = this.suppressDroppingUnrealTables;
                linker.SuppressMsiAssemblyTable     = this.suppressMsiAssemblyTable;
                linker.WixVariableResolver          = this.wixVariableResolver;

                // set the sequence suppression options
                linker.SuppressAdminSequence     = this.suppressAdminSequence;
                linker.SuppressAdvertiseSequence = this.suppressAdvertiseSequence;
                linker.SuppressUISequence        = this.suppressUISequence;

                linker.SectionIdOnRows    = this.sectionIdOnRows;
                linker.GenerateSectionIds = this.generateSectionIds;

                // default the number of cabbing threads to the number of processors if it wasn't specified
                if (0 == this.cabbingThreadCount)
                {
                    string numberOfProcessors = System.Environment.GetEnvironmentVariable("NUMBER_OF_PROCESSORS");

                    try
                    {
                        if (null != numberOfProcessors)
                        {
                            this.cabbingThreadCount = Convert.ToInt32(numberOfProcessors, CultureInfo.InvariantCulture.NumberFormat);

                            if (0 >= this.cabbingThreadCount)
                            {
                                throw new WixException(WixErrors.IllegalEnvironmentVariable("NUMBER_OF_PROCESSORS", numberOfProcessors));
                            }
                        }
                        else // default to 1 if the environment variable is not set
                        {
                            this.cabbingThreadCount = 1;
                        }
                    }
                    catch (ArgumentException)
                    {
                        throw new WixException(WixErrors.IllegalEnvironmentVariable("NUMBER_OF_PROCESSORS", numberOfProcessors));
                    }
                    catch (FormatException)
                    {
                        throw new WixException(WixErrors.IllegalEnvironmentVariable("NUMBER_OF_PROCESSORS", numberOfProcessors));
                    }
                }
                binder.CabbingThreadCount = this.cabbingThreadCount;

                binder.SuppressAclReset = this.suppressAclReset;
                binder.SetMsiAssemblyNameFileVersion = this.setMsiAssemblyNameFileVersion;
                binder.SuppressAssemblies            = this.suppressAssemblies;
                binder.SuppressFileHashAndInfo       = this.suppressFileHashAndInfo;

                if (this.suppressFiles)
                {
                    binder.SuppressAssemblies      = true;
                    binder.SuppressFileHashAndInfo = true;
                }

                binder.SuppressLayout      = this.suppressLayout;
                binder.TempFilesLocation   = Environment.GetEnvironmentVariable("WIX_TEMP");
                binder.WixVariableResolver = this.wixVariableResolver;

                validator.TempFilesLocation = Environment.GetEnvironmentVariable("WIX_TEMP");

                if (null != this.cabCachePath || this.reuseCabinets)
                {
                    // ensure the cabinet cache path exists if we are going to use it
                    if (null != this.cabCachePath && !Directory.Exists(this.cabCachePath))
                    {
                        Directory.CreateDirectory(this.cabCachePath);
                    }
                }

                if (null != this.basePaths)
                {
                    foreach (string basePath in this.basePaths)
                    {
                        this.sourcePaths.Add(basePath);
                    }
                }

                // load any extensions
                bool binderExtensionLoaded    = false;
                bool validatorExtensionLoaded = false;
                foreach (string extension in this.extensionList)
                {
                    WixExtension wixExtension = WixExtension.Load(extension);

                    linker.AddExtension(wixExtension);

                    if (null != wixExtension.BinderExtension)
                    {
                        if (binderExtensionLoaded)
                        {
                            throw new ArgumentException(String.Format(CultureInfo.InvariantCulture, "cannot load binder extension: {0}.  light can only load one binder extension and has already loaded binder extension: {1}.", wixExtension.BinderExtension.GetType().ToString(), binder.Extension.ToString()), "ext");
                        }

                        binder.Extension      = wixExtension.BinderExtension;
                        binderExtensionLoaded = true;
                    }

                    ValidatorExtension validatorExtension = wixExtension.ValidatorExtension;
                    if (null != validatorExtension)
                    {
                        if (validatorExtensionLoaded)
                        {
                            throw new ArgumentException(String.Format(CultureInfo.InvariantCulture, "cannot load linker extension: {0}.  light can only load one link extension and has already loaded link extension: {1}.", validatorExtension.GetType().ToString(), validator.Extension.ToString()), "ext");
                        }

                        validator.Extension      = validatorExtension;
                        validatorExtensionLoaded = true;
                    }
                }

                // set the message handlers
                linker.Message += new MessageEventHandler(this.messageHandler.Display);
                binder.Message += new MessageEventHandler(this.messageHandler.Display);
                validator.Extension.Message += new MessageEventHandler(this.messageHandler.Display);

                Output output = null;

                // instantiate the localizer and load any localization files
                if (0 < this.localizationFiles.Count || null != this.cultures || !this.outputXml)
                {
                    localizer = new Localizer();

                    localizer.Message += new MessageEventHandler(this.messageHandler.Display);

                    // load each localization file
                    foreach (string localizationFile in this.localizationFiles)
                    {
                        Localization localization = Localization.Load(localizationFile, linker.TableDefinitions, this.suppressSchema);

                        localizer.AddLocalization(localization);
                    }

                    // immediately stop processing if any errors were found
                    if (this.messageHandler.EncounteredError)
                    {
                        return(this.messageHandler.LastErrorNumber);
                    }
                }

                // loop through all the believed object files
                foreach (string inputFile in this.inputFiles)
                {
                    string dirName           = Path.GetDirectoryName(inputFile);
                    string inputFileFullPath = Path.GetFullPath(inputFile);

                    if (!this.sourcePaths.Contains(dirName))
                    {
                        this.sourcePaths.Add(dirName);
                    }

                    // try loading as an object file
                    try
                    {
                        Intermediate intermediate = Intermediate.Load(inputFileFullPath, linker.TableDefinitions, this.suppressVersionCheck, this.suppressSchema);
                        sections.AddRange(intermediate.Sections);
                        continue; // next file
                    }
                    catch (WixNotIntermediateException)
                    {
                        // try another format
                    }

                    // try loading as a library file
                    try
                    {
                        Library library = Library.Load(inputFileFullPath, linker.TableDefinitions, this.suppressVersionCheck, this.suppressSchema);
                        sections.AddRange(library.Sections);

                        // load the localization files for the selected cultures
                        if (null != this.cultures)
                        {
                            Localization localization = library.GetLocalization(this.cultures);

                            if (null != localization)
                            {
                                localizer.AddLocalization(localization);
                            }
                        }

                        continue; // next file
                    }
                    catch (WixNotLibraryException)
                    {
                        // try another format
                    }

                    // try loading as an output file
                    output = Output.Load(inputFileFullPath, this.suppressVersionCheck, this.suppressSchema);
                }

                // immediately stop processing if any errors were found
                if (this.messageHandler.EncounteredError)
                {
                    return(this.messageHandler.LastErrorNumber);
                }

                // set the binder extension information
                foreach (string basePath in this.basePaths)
                {
                    binder.Extension.BasePaths.Add(basePath);
                }
                binder.Extension.CabCachePath  = this.cabCachePath;
                binder.Extension.ReuseCabinets = this.reuseCabinets;
                foreach (string sourcePath in this.sourcePaths)
                {
                    binder.Extension.SourcePaths.Add(sourcePath);
                }

                // and now for the fun part
                if (null == output)
                {
                    // tell the linker about the localizer
                    linker.Localizer = localizer;
                    localizer        = null;

                    output = linker.Link(sections, transforms);

                    // if an error occurred during linking, stop processing
                    if (null == output)
                    {
                        return(this.messageHandler.LastErrorNumber);
                    }
                }
                else if (0 != sections.Count)
                {
                    throw new InvalidOperationException("Cannot link object files (.wixobj) files with an output file (.wixout)");
                }

                // Now that the output object is either linked or loaded, tell the binder extension about it.
                binder.Extension.Output = output;

                // only output the xml if its a patch build or user specfied to only output wixout
                if (this.outputXml || OutputType.Patch == output.Type)
                {
                    string outputExtension = Path.GetExtension(this.outputFile);
                    if (null == outputExtension || 0 == outputExtension.Length || ".wix" == outputExtension)
                    {
                        if (OutputType.Patch == output.Type)
                        {
                            this.outputFile = Path.ChangeExtension(this.outputFile, ".wixmsp");
                        }
                        else
                        {
                            this.outputFile = Path.ChangeExtension(this.outputFile, ".wixout");
                        }
                    }
                    output.Save(this.outputFile, (this.bindFiles ? binder.Extension : null), this.wixVariableResolver, binder.TempFilesLocation);
                }
                else // finish creating the MSI/MSM
                {
                    string outputExtension = Path.GetExtension(this.outputFile);
                    if (null == outputExtension || 0 == outputExtension.Length || ".wix" == outputExtension)
                    {
                        if (OutputType.Module == output.Type)
                        {
                            this.outputFile = Path.ChangeExtension(this.outputFile, ".msm");
                        }
                        else if (OutputType.PatchCreation == output.Type)
                        {
                            this.outputFile = Path.ChangeExtension(this.outputFile, ".pcp");
                        }
                        else
                        {
                            this.outputFile = Path.ChangeExtension(this.outputFile, ".msi");
                        }
                    }

                    // tell the binder about the localizer
                    binder.Localizer = localizer;

                    // tell the binder about the validator if validation isn't suppressed
                    if (!this.suppressValidation && (OutputType.Module == output.Type || OutputType.Product == output.Type))
                    {
                        // set the default cube file
                        Assembly lightAssembly  = Assembly.GetExecutingAssembly();
                        string   lightDirectory = Path.GetDirectoryName(lightAssembly.Location);
                        if (OutputType.Module == output.Type)
                        {
                            validator.AddCubeFile(Path.Combine(lightDirectory, "mergemod.cub"));
                        }
                        else // product
                        {
                            validator.AddCubeFile(Path.Combine(lightDirectory, "darice.cub"));
                        }

                        // disable ICE33 by default
                        this.suppressICEs.Add("ICE33");

                        // set the suppressed ICEs
                        string[] suppressICEArray = new string[this.suppressICEs.Count];
                        this.suppressICEs.CopyTo(suppressICEArray, 0);
                        validator.SuppressedICEs = suppressICEArray;

                        binder.Validator = validator;
                    }

                    binder.Bind(output, this.outputFile);
                }
            }
            catch (WixException we)
            {
                if (we is WixInvalidIdtException)
                {
                    // make sure the IDT files stay around
                    this.tidy = false;
                }

                this.messageHandler.Display(this, we.Error);
            }
            catch (Exception e)
            {
                // make sure the files stay around for debugging
                this.tidy = false;

                this.messageHandler.Display(this, WixErrors.UnexpectedException(e.Message, e.GetType().ToString(), e.StackTrace));
                if (e is NullReferenceException || e is SEHException)
                {
                    throw;
                }
            }
            finally
            {
                if (null != binder)
                {
                    if (this.tidy)
                    {
                        if (!binder.DeleteTempFiles())
                        {
                            Console.WriteLine("Warning, failed to delete temporary directory: {0}", binder.TempFilesLocation);
                        }
                    }
                    else
                    {
                        Console.WriteLine("Binder temporary directory located at '{0}'.", binder.TempFilesLocation);
                    }
                }

                if (null != validator)
                {
                    if (this.tidy)
                    {
                        if (!validator.DeleteTempFiles())
                        {
                            Console.WriteLine("Warning, failed to delete temporary directory: {0}", validator.TempFilesLocation);
                        }
                    }
                    else
                    {
                        Console.WriteLine("Validator temporary directory located at '{0}'.", validator.TempFilesLocation);
                    }
                }
            }

            return(this.messageHandler.LastErrorNumber);
        }