public Wix.Wix Decompile(Output output) { if (null == output) { throw new ArgumentNullException("output"); } this.codepage = output.Codepage; this.outputType = output.Type; // collect the table definitions from the output this.tableDefinitions.Clear(); foreach (Table table in output.Tables) { this.tableDefinitions.Add(table.Definition); } // add any missing standard and wix-specific table definitions foreach (TableDefinition tableDefinition in Installer.GetTableDefinitions()) { if (!this.tableDefinitions.Contains(tableDefinition.Name)) { this.tableDefinitions.Add(tableDefinition); } } // add any missing extension table definitions foreach (WixExtension extension in this.extensions) { if (null != extension.TableDefinitions) { foreach (TableDefinition tableDefinition in extension.TableDefinitions) { if (!this.tableDefinitions.Contains(tableDefinition.Name)) { this.tableDefinitions.Add(tableDefinition); } } } } // if we don't have the temporary files object yet, get one if (null == this.tempFiles) { this.TempFilesLocation = null; } Directory.CreateDirectory(this.tempFiles.BasePath); // ensure the base path is there bool encounteredError = false; Wix.IParentElement rootElement; Wix.Wix wixElement = new Wix.Wix(); switch (this.outputType) { case OutputType.Module: rootElement = new Wix.Module(); break; case OutputType.PatchCreation: rootElement = new Wix.PatchCreation(); break; case OutputType.Product: rootElement = new Wix.Product(); break; default: throw new InvalidOperationException(WixStrings.EXP_UnknownOutputType); } wixElement.AddChild((Wix.ISchemaElement)rootElement); // try to decompile the database file try { this.core = new DecompilerCore(rootElement, this.Message); this.core.ShowPedanticMessages = this.showPedanticMessages; // stop processing if an error previously occurred if (this.core.EncounteredError) { return null; } // initialize the decompiler and its extensions foreach (WixExtension extension in this.extensions) { if (null != extension.DecompilerExtension) { extension.DecompilerExtension.Core = this.core; extension.DecompilerExtension.InitializeDecompile(output.Tables); } } this.InitializeDecompile(output.Tables); // stop processing if an error previously occurred if (this.core.EncounteredError) { return null; } // decompile the tables this.DecompileTables(output); // finalize the decompiler and its extensions this.FinalizeDecompile(output.Tables); foreach (WixExtension extension in this.extensions) { if (null != extension.DecompilerExtension) { extension.DecompilerExtension.FinalizeDecompile(output.Tables); } } } finally { encounteredError = this.core.EncounteredError; this.core = null; foreach (WixExtension extension in this.extensions) { if (null != extension.DecompilerExtension) { extension.DecompilerExtension.Core = null; } } } // return the root element only if decompilation completed successfully return (encounteredError ? null : wixElement); }
/// <summary> /// main entry point /// </summary> /// <param name="inputPath">input path.</param> /// <param name="outputPath">output path.</param> public void Decompile(string inputPath, string outputPath) { this.standardActions = Common.GetStandardActions(); if (null == inputPath) { throw new ArgumentNullException("inputPath", "Input file must be specified."); } if (null == outputPath) { throw new ArgumentNullException("outputPath", "Output path must be specified."); } if (!File.Exists(inputPath)) { throw new FileNotFoundException("Cannot find file to decompile.", inputPath); } if (!Path.IsPathRooted(inputPath)) { inputPath = Path.GetFullPath(inputPath); } if (!Path.IsPathRooted(outputPath)) { outputPath = Path.GetFullPath(outputPath); } XmlTextWriter writer = null; try { // remember the output folder and open the database this.outputFolder = Path.GetDirectoryName(outputPath); if (0 == this.outputFolder.Length) { this.outputFolder = System.Environment.CurrentDirectory; } if (null == this.exportBasePath || 0 == this.exportBasePath.Length) { this.exportBasePath = this.outputFolder; } else if (!Path.IsPathRooted(this.exportBasePath)) { this.exportBasePath = Path.GetFullPath(Path.Combine(this.outputFolder, this.exportBasePath)); } // create a temporary directory this.extractFolder = Path.Combine(this.exportBasePath, "extract"); Directory.CreateDirectory(this.extractFolder); this.imageFolder = Path.GetDirectoryName(inputPath); if (null == this.imageBasePath || 0 == this.imageBasePath.Length) { this.imageBasePath = this.imageFolder; } else if (!Path.IsPathRooted(this.imageBasePath)) { this.imageBasePath = Path.GetFullPath(Path.Combine(this.imageFolder, this.imageBasePath)); } if (!Directory.Exists(this.exportBasePath)) { Directory.CreateDirectory(this.exportBasePath); } using (this.inputDatabase = new Database(inputPath, OpenDatabase.ReadOnly)) { using (MemoryStream memoryStream = new MemoryStream()) { using (StreamWriter streamWriter = new StreamWriter(memoryStream, Encoding.UTF8)) { writer = new XmlTextWriter(streamWriter); // use indenting for readability writer.Formatting = Formatting.Indented; this.core = new DecompilerCore(writer, this.Message); this.core.AddComments = this.addComments; // process the reader into the writer try { foreach (DecompilerExtension extension in this.extensionList) { extension.Core = this.core; extension.Messages = this.extensionMessages; extension.InitializeDecompile(); } // do the actual processing to an internal buffer this.ProcessProductElement(true); } // throw an exception catch (XmlException e) { // todo: throw a real exception throw e; } // if no error was found, save the result to the specified file if (!this.foundError) { writer.Flush(); using (FileStream fileStream = File.Create(outputPath)) { memoryStream.WriteTo(fileStream); } } } } } } finally { if (null != writer) { writer.Close(); writer = null; } foreach (XmlWriter fragmentWriter in this.openFragments.Values) { fragmentWriter.Close(); } this.inputDatabase = null; this.outputFolder = null; if (!this.tidy) { Console.WriteLine("Tidy set to false; files can be found at '{0}'.", this.extractFolder); } else { this.DeleteTempFiles(this.extractFolder); } } }