Exemplo n.º 1
0
        public void CanBuildInstanceTransform()
        {
            var folder = TestData.Get(@"TestData\InstanceTransform");

            using (var fs = new DisposableFileSystem())
            {
                var intermediateFolder = fs.GetFolder();

                var result = WixRunner.Execute(new[]
                {
                    "build",
                    Path.Combine(folder, "Package.wxs"),
                    Path.Combine(folder, "PackageComponents.wxs"),
                    "-loc", Path.Combine(folder, "Package.en-us.wxl"),
                    "-bindpath", Path.Combine(folder, "data"),
                    "-intermediateFolder", intermediateFolder,
                    "-o", Path.Combine(intermediateFolder, @"bin\test.msi")
                }, out var messages);

                Assert.Equal(0, result);

                var pdb = Pdb.Load(Path.Combine(intermediateFolder, @"bin\test.wixpdb"), false);
                Assert.NotEmpty(pdb.Output.SubStorages);
            }
        }
Exemplo n.º 2
0
        public void CanLoadPdbGeneratedByBuild()
        {
            var folder = TestData.Get(@"TestData\MultiFileCompressed");

            using (var fs = new DisposableFileSystem())
            {
                var intermediateFolder = fs.GetFolder();

                var result = WixRunner.Execute(new[]
                {
                    "build",
                    Path.Combine(folder, "Package.wxs"),
                    Path.Combine(folder, "PackageComponents.wxs"),
                    "-d", "MediaTemplateCompressionLevel",
                    "-loc", Path.Combine(folder, "Package.en-us.wxl"),
                    "-bindpath", Path.Combine(folder, "data"),
                    "-intermediateFolder", intermediateFolder,
                    "-o", Path.Combine(intermediateFolder, @"bin\test.msi")
                }, out var messages);

                Assert.Equal(0, result);

                Assert.True(File.Exists(Path.Combine(intermediateFolder, @"bin\test.msi")));
                Assert.True(File.Exists(Path.Combine(intermediateFolder, @"bin\cab1.cab")));

                var pdbPath = Path.Combine(intermediateFolder, @"bin\test.wixpdb");
                Assert.True(File.Exists(pdbPath));

                var pdb = Pdb.Load(pdbPath, suppressVersionCheck: true);
                Assert.NotNull(pdb);
                Assert.NotNull(pdb.Output);
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Extracts files from an MSI database and rewrites the paths embedded in the source .wixpdb to the output .wixpdb.
        /// </summary>
        private void MeltProduct()
        {
            // print friendly message saying what file is being decompiled
            Console.WriteLine("{0} / {1}", Path.GetFileName(this.inputFile), Path.GetFileName(this.inputPdbFile));

            // extract files from the .msi (unless suppressed) and get the path map of File ids to target paths
            string outputDirectory             = this.exportBasePath ?? Environment.GetEnvironmentVariable("WIX_TEMP");
            IDictionary <string, string> paths = null;

            using (InstallPackage package = new InstallPackage(this.inputFile, DatabaseOpenMode.ReadOnly, null, outputDirectory))
            {
                if (!this.suppressExtraction)
                {
                    package.ExtractFiles();
                }

                paths = package.Files.SourcePaths;
            }

            Pdb   inputPdb     = Pdb.Load(this.inputPdbFile, true, true);
            Table wixFileTable = inputPdb.Output.Tables["WixFile"];

            if (null != wixFileTable)
            {
                foreach (Row row in wixFileTable.Rows)
                {
                    WixFileRow fileRow = row as WixFileRow;
                    if (null != fileRow)
                    {
                        string newPath;
                        if (paths.TryGetValue(fileRow.File, out newPath))
                        {
                            fileRow.Source = Path.Combine(outputDirectory, newPath);
                        }
                    }
                }
            }

            string tempPath = Path.Combine(Environment.GetEnvironmentVariable("WIX_TEMP") ?? Path.GetTempPath(), Path.GetRandomFileName());

            try
            {
                inputPdb.Save(this.outputFile, null, null, tempPath);
            }
            finally
            {
                if (this.tidy)
                {
                    if (!AppCommon.DeleteDirectory(tempPath, this.messageHandler))
                    {
                        Console.WriteLine(MeltStrings.WAR_FailedToDeleteTempDir, tempPath);
                    }
                }
                else
                {
                    Console.WriteLine(MeltStrings.INF_TempDirLocatedAt, tempPath);
                }
            }
        }
        /// <summary>
        /// Extracts files from an MSI database and rewrites the paths embedded in the source .wixpdb to the output .wixpdb.
        /// </summary>
        private void MeltProduct()
        {
            // print friendly message saying what file is being decompiled
            Console.WriteLine("{0} / {1}", Path.GetFileName(this.inputFile), Path.GetFileName(this.inputPdbFile));

            Pdb inputPdb = Pdb.Load(this.inputPdbFile, true);

            // extract files from the .msi (unless suppressed) and get the path map of File ids to target paths
            string outputDirectory             = this.exportBasePath ?? Environment.GetEnvironmentVariable("WIX_TEMP");
            IDictionary <string, string> paths = null;

            using (InstallPackage package = new InstallPackage(this.inputFile, DatabaseOpenMode.ReadOnly, null, outputDirectory))
            {
                // ignore failures as this is a new validation in v3.x
                ValidateMsiMatchesPdb(package, inputPdb);

                if (!this.suppressExtraction)
                {
                    package.ExtractFiles();
                }

                paths = package.Files.SourcePaths;
            }

            Table wixFileTable = inputPdb.Output.Tables["WixFile"];

            if (null != wixFileTable)
            {
                foreach (Row row in wixFileTable.Rows)
                {
                    WixFileRow fileRow = row as WixFileRow;
                    if (null != fileRow)
                    {
                        string newPath;
                        if (paths.TryGetValue(fileRow.File, out newPath))
                        {
                            fileRow.Source = Path.Combine(outputDirectory, newPath);
                        }
                    }
                }
            }

            inputPdb.Save(this.outputFile);
        }
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 (0 == this.inputFiles.Count)
                {
                    this.showHelp = true;
                }

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

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

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

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

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

                    ValidatorExtension validatorExtension = wixExtension.ValidatorExtension;
                    if (null != validatorExtension)
                    {
                        if (validatorExtensionLoaded)
                        {
                            throw new ArgumentException(String.Format(CultureInfo.CurrentUICulture, SmokeStrings.EXP_CannotLoadLinkerExtension, validatorExtension.GetType().ToString(), validator.Extension.ToString()), "ext");
                        }

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

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

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

                // set the ICEs
                string[] iceArray = new string[this.ices.Count];
                this.ices.CopyTo(iceArray, 0);
                validator.ICEs = iceArray;

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

                // Load the pdb and assign the Output to the validator
                if (null != pdbPath)
                {
                    string pdbFullPath = Path.GetFullPath(pdbPath);
                    Pdb    pdb         = Pdb.Load(pdbFullPath, false, false);
                    this.validator.Output = pdb.Output;
                }

                foreach (string inputFile in this.inputFiles)
                {
                    // set the default cube file
                    Assembly assembly     = Assembly.GetExecutingAssembly();
                    string   appDirectory = Path.GetDirectoryName(assembly.Location);

                    if (this.addDefault)
                    {
                        switch (Path.GetExtension(inputFile).ToLower(CultureInfo.InvariantCulture))
                        {
                        case msm:
                            validator.AddCubeFile(Path.Combine(appDirectory, "mergemod.cub"));
                            break;

                        case msi:
                            validator.AddCubeFile(Path.Combine(appDirectory, "darice.cub"));
                            break;

                        default:
                            throw new WixException(WixErrors.UnexpectedFileExtension(inputFile, ".msi, .msm"));
                        }
                    }

                    // print friendly message saying what file is being validated
                    Console.WriteLine(Path.GetFileName(inputFile));
                    Stopwatch stopwatch = Stopwatch.StartNew();

                    try
                    {
                        validator.Validate(Path.GetFullPath(inputFile));
                    }
                    catch (UnauthorizedAccessException)
                    {
                        this.messageHandler.Display(this, WixErrors.UnauthorizedAccess(Path.GetFullPath(inputFile)));
                    }
                    finally
                    {
                        stopwatch.Stop();
                        this.messageHandler.Display(this, WixVerboses.ValidatedDatabase(stopwatch.ElapsedMilliseconds));

                        if (this.tidy)
                        {
                            if (!validator.DeleteTempFiles())
                            {
                                Console.WriteLine(SmokeStrings.WAR_FailedToDeleteTempDir, validator.TempFilesLocation);
                            }
                        }
                        else
                        {
                            Console.WriteLine(SmokeStrings.INF_TempDirLocatedAt, validator.TempFilesLocation);
                        }
                    }
                }
            }
            catch (WixException we)
            {
                this.messageHandler.Display(this, we.Error);
            }
            catch (Exception e)
            {
                this.messageHandler.Display(this, WixErrors.UnexpectedException(e.Message, e.GetType().ToString(), e.StackTrace));
                if (e is NullReferenceException || e is SEHException)
                {
                    throw;
                }
            }

            return(this.messageHandler.LastErrorNumber);
        }