/// <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> /// 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 (Messaging.Instance.EncounteredError) { return(Messaging.Instance.LastErrorNumber); } if (0 == this.inputFiles.Count) { this.showHelp = true; } if (this.showLogo) { AppCommon.DisplayToolHeader(); } if (this.showHelp) { Console.WriteLine(SmokeStrings.HelpMessage); AppCommon.DisplayToolFooter(); return(Messaging.Instance.LastErrorNumber); } foreach (string parameter in this.invalidArgs) { Messaging.Instance.OnMessage(WixWarnings.UnsupportedCommandLineArgument(parameter)); } this.invalidArgs = null; string tempFilesLocation = AppCommon.GetTempLocation(); validator.TempFilesLocation = tempFilesLocation; // TODO: rename ValidatorExtensions to "ValidatorFilterExtension" or something like that. Actually, // revisit all of this as we try to build a more generic validation system around ICEs. // // 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; // } //} // 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); 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) { Messaging.Instance.OnMessage(WixErrors.UnauthorizedAccess(Path.GetFullPath(inputFile))); } finally { stopwatch.Stop(); Messaging.Instance.OnMessage(WixVerboses.ValidatedDatabase(stopwatch.ElapsedMilliseconds)); if (this.tidy) { if (!AppCommon.DeleteDirectory(tempFilesLocation, Messaging.Instance)) { Console.Error.WriteLine(SmokeStrings.WAR_FailedToDeleteTempDir, tempFilesLocation); } } else { Console.WriteLine(SmokeStrings.INF_TempDirLocatedAt, tempFilesLocation); } } } } catch (WixException we) { Messaging.Instance.OnMessage(we.Error); } catch (Exception e) { Messaging.Instance.OnMessage(WixErrors.UnexpectedException(e.Message, e.GetType().ToString(), e.StackTrace)); if (e is NullReferenceException || e is SEHException) { throw; } } return(Messaging.Instance.LastErrorNumber); }