/// <summary> /// Decompile the FileShare table. /// </summary> /// <param name="table">The table to decompile.</param> private void DecompileFileShareTable(Table table) { foreach (Row row in table.Rows) { Util.FileShare fileShare = new Util.FileShare(); fileShare.Id = (string)row[0]; fileShare.Name = (string)row[1]; if (null != row[3]) { fileShare.Description = (string)row[3]; } // the Directory_ column is set by the parent Component // the User_ and Permissions columns are deprecated Wix.Component component = (Wix.Component) this.Core.GetIndexedElement("Component", (string)row[2]); if (null != component) { component.AddChild(fileShare); } else { this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerCore.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component")); } this.Core.IndexElement(row, fileShare); } }
/// <summary> /// Harvest a file. /// </summary> /// <param name="argument">The path of the file.</param> /// <returns>A harvested file.</returns> public override Wix.Fragment Harvest(string argument) { if (null == argument) { throw new ArgumentNullException("argument"); } Wix.File file = this.HarvestFile(argument); Wix.Component component = new Wix.Component(); component.AddChild(file); string directoryPath = Path.GetDirectoryName(Path.GetFullPath(argument)); Wix.Directory directory = new Wix.Directory(); directory.FileSource = directoryPath; directory.Name = Path.GetFileName(directoryPath); directory.AddChild(component); Wix.DirectoryRef directoryRef = new Wix.DirectoryRef(); directoryRef.Id = "TARGETDIR"; directoryRef.AddChild(directory); Wix.Fragment fragment = new Wix.Fragment(); fragment.AddChild(directoryRef); return(fragment); }
/// <summary> /// Mutate a file. /// </summary> /// <param name="parentElement">The parent of the element to mutate.</param> /// <param name="file">The file to mutate.</param> private string GetFilePathFromComponent(Wix.Component element, String filename, bool isFileExtension) { ArrayList childElements = new ArrayList(); // copy the child elements to a temporary array (to allow them to be deleted/moved) foreach (Wix.ISchemaElement childElement in ((Wix.IParentElement)element).Children) { childElements.Add(childElement); } foreach (Wix.ISchemaElement childElement in childElements) { if (childElement is Wix.File) { if (isFileExtension) { if (0 == String.Compare(filename, Path.GetExtension(((Wix.File)childElement).Source), true)) { return(((Wix.File)childElement).Source); } } else { if (0 == String.Compare(filename, Path.GetFileName(((Wix.File)childElement).Source), true)) { return(((Wix.File)childElement).Source); } } } } return(null); }
/// <summary> /// Decompile the MessageQueueGroupPermission table. /// </summary> /// <param name="table">The table to decompile.</param> private void DecompileMessageQueueGroupPermissionTable(Table table) { foreach (Row row in table.Rows) { Msmq.MessageQueuePermission queuePermission = new Msmq.MessageQueuePermission(); queuePermission.Id = (string)row[0]; if (null != row[2]) { queuePermission.MessageQueue = (string)row[2]; } queuePermission.Group = (string)row[3]; DecompileMessageQueuePermissionAttributes(row, queuePermission); Wix.Component component = (Wix.Component) this.Core.GetIndexedElement("Component", (string)row[1]); if (null != component) { component.AddChild(queuePermission); } else { this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerCore.PrimaryKeyDelimiter), "Component_", (string)row[1], "Component")); } } }
/// <summary> /// Harvest a WiX document. /// </summary> /// <param name="argument">The argument for harvesting.</param> /// <returns>The harvested Fragment.</returns> public override Wix.Fragment[] Harvest(string argument) { DirectoryHarvester directoryHarvester = new DirectoryHarvester(); directoryHarvester.Core = this.Core; directoryHarvester.KeepEmptyDirectories = true; IIsWebSiteHarvester iisWebSiteHarvester = new IIsWebSiteHarvester(); iisWebSiteHarvester.Core = this.Core; IIs.WebSite webSite = iisWebSiteHarvester.HarvestWebSite(argument); Wix.Component component = new Wix.Component(); component.AddChild(new Wix.CreateFolder()); component.AddChild(webSite); this.Core.RootDirectory = webSite.Directory; Wix.Directory directory = directoryHarvester.HarvestDirectory(webSite.Directory, true); directory.AddChild(component); Wix.Fragment fragment = new Wix.Fragment(); fragment.AddChild(directory); return(new Wix.Fragment[] { fragment }); }
/// <summary> /// Mutate a WiX document. /// </summary> /// <param name="wix">The Wix document element.</param> public override void Mutate(Wix.Wix wix) { //Remove the inf file from the package Wix.Component InfComponent = this.GetComponentWithFileFromWix(null, wix, ".inf", true); String InfPath = GetFilePathFromComponent(InfComponent, ".inf", true); if (InfPath != null) { ((Wix.IParentElement)((Wix.ISchemaElement)InfComponent).ParentElement).RemoveChild(InfComponent); } //Process the inf for the package if (InfPath != null) { InfParser infp = new InfIntrepretor.InfParser(InfPath); infp.ParseIntoSections(); infp.InterpretInfToOpTree(); ProcessInfFile(infp.InfFiles, wix); Wix.Component BinComponent = this.GetComponentWithFileFromWix(null, wix, infp.MainBinFileName, false); this.mainBinFilePath = GetFilePathFromComponent(BinComponent, infp.MainBinFileName, false); } else { //go through and register every file //BUGBUGAddRegistrationInformation(wix); } }
/// <summary> /// Harvest a file. /// </summary> /// <param name="argument">The path of the file.</param> /// <returns>A harvested file.</returns> public override Wix.Fragment[] Harvest(string argument) { if (null == argument) { throw new ArgumentNullException("argument"); } if (null == this.rootedDirectoryRef) { this.rootedDirectoryRef = "TARGETDIR"; } string fullPath = Path.GetFullPath(argument); Wix.DirectoryRef directoryRef = new Wix.DirectoryRef(); directoryRef.Id = this.rootedDirectoryRef; Wix.File file = this.HarvestFile(fullPath); if (!this.suppressRootDirectory) { file.Source = String.Concat("SourceDir\\", Path.GetFileName(Path.GetDirectoryName(fullPath)), "\\", Path.GetFileName(fullPath)); } Wix.Component component = new Wix.Component(); component.AddChild(file); Wix.Directory directory = new Wix.Directory(); if (this.suppressRootDirectory) { directoryRef.AddChild(component); } else { string directoryPath = Path.GetDirectoryName(Path.GetFullPath(argument)); directory.Name = Path.GetFileName(directoryPath); if (this.setUniqueIdentifiers) { directory.Id = this.Core.GenerateIdentifier(DirectoryPrefix, directoryRef.Id, directory.Name); } directory.AddChild(component); directoryRef.AddChild(directory); } if (this.setUniqueIdentifiers) { file.Id = this.Core.GenerateIdentifier(FilePrefix, (this.suppressRootDirectory) ? directoryRef.Id : directory.Id, Path.GetFileName(file.Source)); component.Id = this.Core.GenerateIdentifier(ComponentPrefix, (this.suppressRootDirectory) ? directoryRef.Id : directory.Id, file.Id); } Wix.Fragment fragment = new Wix.Fragment(); fragment.AddChild(directoryRef); return(new Wix.Fragment[] { fragment }); }
public static void ExtractWxsResource(FileInfo fi, Component wixComponent) { byte[] data = ReadNativeResource(fi); XmlDocument xml = GetXmlDocument(data); Component wixComponentOuter = ParseComponent(xml); CopyRegistry(wixComponentOuter, wixComponent); }
/// <summary> /// Converts the registry key to a WiX component element. /// </summary> /// <param name="sr">The registry file stream.</param> /// <param name="directory">A WiX directory reference.</param> /// <param name="root">The root key.</param> /// <param name="line">The current line.</param> private void ConvertKey(StreamReader sr, ref Wix.Directory directory, Wix.RegistryRootType root, string line) { Wix.Component component = new Wix.Component(); component.Id = this.Core.GenerateIdentifier(ComponentPrefix, line); component.KeyPath = Wix.YesNoType.yes; this.ConvertValues(sr, ref component, root, line); directory.AddChild(component); }
/// <summary> /// Add a scraped directory to the UI. /// </summary> /// <param name="nodes">The NodeCollection under which the new directory should be added.</param> /// <param name="rootDirectory">Root of the scraped directory info's.</param> /// <param name="directory">The scraped directory to add.</param> /// <param name="skip">true if the directory itself shouldn't be added; false otherwise.</param> private void AddDirectory(TreeNodeCollection nodes, string currentPath, Wix.Directory rootDirectory, Wix.Directory directory, bool skip) { // get the directory icon, add it to the image list, then free it immediately if (!skip) { Icon folderIcon = NativeMethods.GetDirectoryIcon(true, false); DirectoryInfo directoryInfo = new DirectoryInfo(Path.Combine(currentPath, directory.Name)); TreeNode node = (TreeNode)this.Invoke(this.addTreeNodeCallback, new object[] { nodes, folderIcon, directory.Name, directoryInfo, false }); folderIcon.Dispose(); // add sub-directories and files to this node nodes = node.Nodes; currentPath = Path.Combine(currentPath, directory.Name); } foreach (Wix.ISchemaElement element in directory.Children) { Wix.Component component = element as Wix.Component; if (null != component) { foreach (Wix.ISchemaElement child in component.Children) { Wix.File file = child as Wix.File; if (null != file) { bool selected = false; FileInfo fileInfo = new FileInfo(Path.Combine(currentPath, file.Name)); // if there is no application entry point and we've found an executable make this the application entry point if (this.packageBuilder.ApplicationEntry == null && String.Compare(fileInfo.Extension, ".exe", true, CultureInfo.InvariantCulture) == 0) { //this.packageBuilder.ApplicationEntry = fileInfo.FullName.Substring(rootDirectory.FullName.Length + 1); selected = true; } // get the file icon, add it to the image list, then free it immediately Icon fileIcon = NativeMethods.GetFileIcon(fileInfo.FullName, true, false); this.Invoke(this.addTreeNodeCallback, new object[] { nodes, fileIcon, file.Name, fileInfo, selected }); fileIcon.Dispose(); } } } else { Wix.Directory subDirectory = element as Wix.Directory; if (null != subDirectory) { this.AddDirectory(nodes, currentPath, rootDirectory, subDirectory, false); } } } }
/// <summary> /// Returns the File matching the relative path in the Directory tree. /// </summary> /// <param name="relativePath">Relative path to the file to find in the directory.</param> /// <param name="directory">Directory tree to search for relative path in.</param> private Wix.File GetFile(string relativePath, Wix.Directory rootDirectory) { IEnumerable enumerable = rootDirectory.Children; string[] directory = relativePath.Split(Path.DirectorySeparatorChar); for (int i = 0; i < directory.Length; ++i) { bool found = false; if (i < directory.Length - 1) { foreach (Wix.ISchemaElement element in enumerable) { Wix.Directory childDirectory = element as Wix.Directory; if (null != childDirectory && directory[i] == childDirectory.Name) { enumerable = childDirectory.Children; found = true; break; } } } else { foreach (Wix.ISchemaElement element in enumerable) { Wix.Component component = element as Wix.Component; if (null != component) { foreach (Wix.ISchemaElement child in component.Children) { Wix.File file = child as Wix.File; if (null != file && directory[i] == file.Name) { return(file); } } } } } if (!found) { throw new ApplicationException("Did not find file name"); } } return(null); }
private static void CopyRegistry(Component wixComponentSource, Component wixComponentTarget) { foreach (ISchemaElement child in wixComponentSource.Children) { if ((child is RegistryKey) || (child is RegistryValue)) { wixComponentTarget.AddChild(child); } else { throw new InvalidOperationException(string.Format("Unexpected WiX component child “{0}”.", child.GetType().AssemblyQualifiedName)); } } }
/// <summary> /// Harvest a directory. /// </summary> /// <param name="path">The path of the directory.</param> /// <param name="directory">The directory for this path.</param> /// <returns>The number of files harvested.</returns> private int HarvestDirectory(string path, Wix.Directory directory) { int fileCount = 0; // harvest the child directories foreach (string childDirectoryPath in Directory.GetDirectories(path)) { Wix.Directory childDirectory = new Wix.Directory(); childDirectory.FileSource = childDirectoryPath; childDirectory.Name = Path.GetFileName(childDirectoryPath); int childFileCount = this.HarvestDirectory(childDirectoryPath, childDirectory); // keep the directory if it contained any files (or empty directories are being kept) if (0 < childFileCount || this.keepEmptyDirectories) { directory.AddChild(childDirectory); } fileCount += childFileCount; } // harvest the files string[] files = Directory.GetFiles(path); if (0 < files.Length) { foreach (string filePath in Directory.GetFiles(path)) { Wix.Component component = new Wix.Component(); Wix.File file = this.fileHarvester.HarvestFile(filePath); component.AddChild(file); directory.AddChild(component); } } else if (0 == fileCount && this.keepEmptyDirectories) { Wix.Component component = new Wix.Component(); component.KeyPath = Wix.YesNoType.yes; Wix.CreateFolder createFolder = new Wix.CreateFolder(); component.AddChild(createFolder); directory.AddChild(component); } return(fileCount + files.Length); }
/// <summary> /// Decompile the MsiDriverPackages table. /// </summary> /// <param name="table">The table to decompile.</param> private void DecompileMsiDriverPackagesTable(Table table) { foreach (Row row in table.Rows) { DifxApp.Driver driver = new DifxApp.Driver(); int attributes = (int)row[1]; if (0x1 == (attributes & 0x1)) { driver.ForceInstall = DifxApp.YesNoType.yes; } if (0x2 == (attributes & 0x2)) { driver.PlugAndPlayPrompt = DifxApp.YesNoType.no; } if (0x4 == (attributes & 0x4)) { driver.AddRemovePrograms = DifxApp.YesNoType.no; } if (0x8 == (attributes & 0x8)) { driver.Legacy = DifxApp.YesNoType.yes; } if (0x10 == (attributes & 0x10)) { driver.DeleteFiles = DifxApp.YesNoType.yes; } if (null != row[2]) { driver.Sequence = (int)row[2]; } Wix.Component component = (Wix.Component) this.Core.GetIndexedElement("Component", (string)row[0]); if (null != component) { component.AddChild(driver); } else { this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerCore.PrimaryKeyDelimiter), "Component", (string)row[0], "Component")); } } }
/// <summary> /// Decompiles the WixDependencyProvider table. /// </summary> /// <param name="table">The table to decompile.</param> private void DecompileWixDependencyProviderTable(Table table) { foreach (Row row in table.Rows) { Provides provides = new Provides(); provides.Id = (string)row[0]; provides.Key = (string)row[2]; if (null != row[3]) { provides.Version = (string)row[3]; } if (null != row[4]) { provides.DisplayName = (string)row[4]; } // Nothing to parse for attributes currently. Wix.Component component = (Wix.Component) this.Core.GetIndexedElement("Component", (string)row[1]); if (null != component) { component.AddChild(provides); } else { this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerCore.PrimaryKeyDelimiter), "Component_", (string)row[1], "Component")); } // Index the provider to parent the RequiresRef elements. this.Core.IndexElement(row, provides); // Add the provider-specific registry keys to be removed during finalization. // Only remove specific keys that the compiler writes. string keyProvides = String.Concat(DependencyCommon.RegistryRoot, provides.Key); this.registryValues.Add(keyProvides, null); this.registryValues.Add(keyProvides, "Version"); this.registryValues.Add(keyProvides, "DisplayName"); this.registryValues.Add(keyProvides, "Attributes"); // Cache the provider key. this.keyCache[provides.Id] = provides.Key; } }
/// <summary> /// Walks a directory structure obtaining Component Id's and Standard Directory Id's. /// </summary> /// <param name="directory">The Directory to walk.</param> /// <returns>true if the directory is TARGETDIR.</returns> private bool WalkDirectory(Wix.Directory directory) { bool isTargetDir = false; if ("TARGETDIR" == directory.Id) { isTargetDir = true; } string standardDirectoryId = null; if (Melter.StartsWithStandardDirectoryId(directory.Id, out standardDirectoryId) && !isTargetDir) { this.AddSetPropertyCustomAction(directory.Id, String.Format(CultureInfo.InvariantCulture, "[{0}]", standardDirectoryId)); } foreach (Wix.ISchemaElement child in directory.Children) { Wix.Directory childDir = child as Wix.Directory; if (null != childDir) { if (isTargetDir) { this.primaryDirectoryRef.AddChild(child); } this.WalkDirectory(childDir); } else { Wix.Component childComponent = child as Wix.Component; if (null != childComponent) { if (isTargetDir) { this.primaryDirectoryRef.AddChild(child); } this.AddComponentRef(childComponent); } } } return(isTargetDir); }
/// <summary> /// Harvest a WiX document. /// </summary> /// <param name="argument">The argument for harvesting.</param> /// <returns>The harvested Fragment.</returns> public override Wix.Fragment Harvest(string argument) { Wix.Component component = new Wix.Component(); component.AddChild(new Wix.CreateFolder()); Wix.Fragment fragment = new Wix.Fragment(); // Add in any CAB\DLL\OCX pre-processing here. // get the Internet Component Download type if (argument.StartsWith("ocx:") || argument.StartsWith("dll:")) { fragment = this.HarvestDll(fragment, argument.Substring(4)); } else if (argument.StartsWith("cab:")) { fragment = this.HarvestCab(fragment, argument.Substring(4)); } return(fragment); }
/// <summary> /// Scrapes a directory subtree. /// </summary> /// <param name="target">Directory currently being scraped.</param> private static void ScrapeDirectory(Directory target) { ArrayList subItems = new ArrayList(); foreach (string directory in IO.Directory.GetDirectories(target.FileSource)) { Directory scrapedDirectory = new Directory(); directoryId++; scrapedDirectory.Id = String.Format(CultureInfo.InvariantCulture, "Dir{0}", directoryId); scrapedDirectory.LongName = IO.Path.GetFileName(directory); scrapedDirectory.Name = scrapedDirectory.Id; scrapedDirectory.FileSource = directory; target.AddChild(scrapedDirectory); ScrapeDirectory(scrapedDirectory); } foreach (string file in IO.Directory.GetFiles(target.FileSource)) { File scrapedFile = new File(); scrapedFile.LongName = IO.Path.GetFileName(file); scrapedFile.Source = file; fileId++; string fileExtension = IO.Path.GetExtension(file); if (fileExtension.Length > 4) { scrapedFile.Id = String.Format(CultureInfo.InvariantCulture, "Fil{0}{1}", fileId, fileExtension.Substring(0, 4)); } else { scrapedFile.Id = String.Format(CultureInfo.InvariantCulture, "Fil{0}{1}", fileId, fileExtension); } scrapedFile.Name = scrapedFile.Id; Component fileComponent = new Component(); fileComponent.Id = String.Format(CultureInfo.InvariantCulture, "Comp{0}", scrapedFile.Name); fileComponent.DiskId = 1; fileComponent.Guid = Guid.NewGuid().ToString(); fileComponent.AddChild(scrapedFile); target.AddChild(fileComponent); } }
/// <summary> /// Finalize the XmlConfig table. /// </summary> /// <param name="tables">Collection of all tables.</param> private void FinalizeXmlConfigTable(TableCollection tables) { Table xmlConfigTable = tables["XmlConfig"]; if (null != xmlConfigTable) { foreach (Row row in xmlConfigTable.Rows) { Util.XmlConfig xmlConfig = (Util.XmlConfig) this.Core.GetIndexedElement(row); if (null == row[6] || 0 == (int)row[6]) { Util.XmlConfig parentXmlConfig = (Util.XmlConfig) this.Core.GetIndexedElement("XmlConfig", (string)row[2]); if (null != parentXmlConfig) { parentXmlConfig.AddChild(xmlConfig); } else { this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, xmlConfigTable.Name, row.GetPrimaryKey(DecompilerCore.PrimaryKeyDelimiter), "ElementPath", (string)row[2], "XmlConfig")); } } else { Wix.Component component = (Wix.Component) this.Core.GetIndexedElement("Component", (string)row[7]); if (null != component) { component.AddChild(xmlConfig); } else { this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, xmlConfigTable.Name, row.GetPrimaryKey(DecompilerCore.PrimaryKeyDelimiter), "Component_", (string)row[7], "Component")); } } } } }
/// <summary> /// Mutate the WebFilter elements. /// </summary> private void MutateWebFilters() { IdentifierGenerator identifierGenerator = null; if (this.setUniqueIdentifiers) { identifierGenerator = new IdentifierGenerator("WebFilter"); // index all the existing identifiers and names foreach (IIs.WebFilter webFilter in this.webFilters) { if (null != webFilter.Id) { identifierGenerator.IndexExistingIdentifier(webFilter.Id); } else { identifierGenerator.IndexName(webFilter.Name); } } } foreach (IIs.WebFilter webFilter in this.webFilters) { if (this.setUniqueIdentifiers && null == webFilter.Id) { webFilter.Id = identifierGenerator.GetIdentifier(webFilter.Name); } // harvest the file for this WebFilter Wix.Directory directory = this.HarvestUniqueDirectory(Path.GetDirectoryName(webFilter.Path), false); Wix.Component component = new Wix.Component(); directory.AddChild(component); Wix.File file = this.fileHarvester.HarvestFile(webFilter.Path); component.AddChild(file); } }
/// <summary> /// Returns a ComponentRef for each Component in the Directory tree. /// </summary> /// <param name="directory">The root Directory of the components.</param> /// <returns>Returns all of the Components in a directory.</returns> private Wix.ComponentRef[] GetComponentRefs(Wix.Directory directory) { ArrayList componentRefs = new ArrayList(); foreach (Wix.ISchemaElement element in directory.Children) { if (element is Wix.Component) { Wix.Component component = (Wix.Component)element; Wix.ComponentRef componentRef = new Wix.ComponentRef(); componentRef.Id = component.Id; componentRefs.Add(componentRef); } else if (element is Wix.Directory) { componentRefs.AddRange(this.GetComponentRefs((Wix.Directory)element)); } } return((Wix.ComponentRef[])componentRefs.ToArray(typeof(Wix.ComponentRef))); }
private void ProcessInfFile(List <InfFileInstructions> InfFiles, Wix.Wix wix) { foreach (InfFileInstructions ifi in InfFiles) { Wix.Component FileComponent = this.GetComponentWithFileFromWix(null, wix, ifi.FileName, false); if (null == FileComponent) { Console.WriteLine("Exception: this file wasn't found in the current component..."); } if (mainComponentGuid == null) { mainComponentGuid = Guid.NewGuid().ToString("B").ToUpper(); FileComponent.Guid = mainComponentGuid; } else { FileComponent.Guid = Guid.NewGuid().ToString("B").ToUpper(); } String FilePath = GetFilePathFromComponent(FileComponent, ifi.FileName, false); if (ifi.RegisterServer == "yes") { DllHarvester dh = new DllHarvester(); Wix.RegistryValue[] axregvals = dh.HarvestRegistryValues(FilePath); foreach (Wix.RegistryValue r in axregvals) { FileComponent.AddChild(r); } } } }
/// <summary> /// Harvest a WiX document. /// </summary> /// <param name="argument">The argument for harvesting.</param> /// <returns>The harvested Fragment.</returns> public override Wix.Fragment[] Harvest(string argument) { DirectoryHarvester directoryHarvester = new DirectoryHarvester(); directoryHarvester.Core = this.Core; directoryHarvester.KeepEmptyDirectories = true; IIsWebSiteHarvester iisWebSiteHarvester = new IIsWebSiteHarvester(); iisWebSiteHarvester.Core = this.Core; IIs.WebSite webSite = iisWebSiteHarvester.HarvestWebSite(argument); Wix.Component component = new Wix.Component(); component.AddChild(new Wix.CreateFolder()); component.AddChild(webSite); this.Core.RootDirectory = webSite.Directory; Wix.Directory directory = directoryHarvester.HarvestDirectory(webSite.Directory, true); directory.AddChild(component); Wix.Fragment fragment = new Wix.Fragment(); fragment.AddChild(directory); return new Wix.Fragment[] { fragment }; }
/// <summary> /// Mutate an element. /// </summary> /// <param name="parentElement">The parent of the element to mutate.</param> /// <param name="element">The element to mutate.</param> private Wix.Component GetComponentWithFileFromWix(Wix.IParentElement parentElement, Wix.ISchemaElement element, String FileName, bool isExtension) { String InfFilePath = null; if (element is Wix.Component) { if ((InfFilePath = this.GetFilePathFromComponent((Wix.Component)element, FileName, isExtension)) != null) { //we return once we see an inf file return((Wix.Component)element); } } if (element is Wix.IParentElement) { ArrayList childElements = new ArrayList(); foreach (Wix.ISchemaElement childElement in ((Wix.IParentElement)element).Children) { childElements.Add(childElement); } foreach (Wix.ISchemaElement childElement in childElements) { Wix.Component comp = GetComponentWithFileFromWix((Wix.IParentElement)element, childElement, FileName, isExtension); if (comp != null) { return(comp); } } } return(null); }
/// <summary> /// Harvest a performance category. /// </summary> /// <param name="argument">The name of the performance category.</param> /// <returns>A harvested performance category.</returns> public override Wix.Fragment[] Harvest(string argument) { if (null == argument) { throw new ArgumentNullException("argument"); } Util.PerformanceCategory perf = this.HarvestPerformanceCategory(argument); Wix.Component component = new Wix.Component(); component.Id = CompilerCore.GetIdentifierFromName(argument); component.KeyPath = Wix.YesNoType.yes; component.AddChild(perf); Wix.Directory directory = new Wix.Directory(); directory.Id = "TARGETDIR"; //directory.Name = directory.Id; directory.AddChild(component); Wix.Fragment fragment = new Wix.Fragment(); fragment.AddChild(directory); return new Wix.Fragment[] { fragment }; }
/// <summary> /// Harvest a performance category. /// </summary> /// <param name="argument">The name of the performance category.</param> /// <returns>A harvested performance category.</returns> public override Wix.Fragment[] Harvest(string argument) { if (null == argument) { throw new ArgumentNullException("argument"); } Util.PerformanceCategory perf = this.HarvestPerformanceCategory(argument); Wix.Component component = new Wix.Component(); component.Id = CompilerCore.GetIdentifierFromName(argument); component.KeyPath = Wix.YesNoType.yes; component.AddChild(perf); Wix.Directory directory = new Wix.Directory(); directory.Id = "TARGETDIR"; //directory.Name = directory.Id; directory.AddChild(component); Wix.Fragment fragment = new Wix.Fragment(); fragment.AddChild(directory); return(new Wix.Fragment[] { fragment }); }
/// <summary> /// Decompile the WixHttpUrlReservation table. /// </summary> /// <param name="table">The table to decompile.</param> private void DecompileWixHttpUrlReservationTable(Table table) { foreach (Row row in table.Rows) { Http.UrlReservation urlReservation = new Http.UrlReservation(); urlReservation.Id = (string)row[0]; switch ((int)row[1]) { case HttpConstants.heReplace: default: urlReservation.HandleExisting = Http.UrlReservation.HandleExistingType.replace; break; case HttpConstants.heIgnore: urlReservation.HandleExisting = Http.UrlReservation.HandleExistingType.ignore; break; case HttpConstants.heFail: urlReservation.HandleExisting = Http.UrlReservation.HandleExistingType.fail; break; } urlReservation.Sddl = (string)row[2]; urlReservation.Url = (string)row[3]; Wix.Component component = (Wix.Component) this.Core.GetIndexedElement("Component", (string)row[4]); if (null != component) { component.AddChild(urlReservation); } else { this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerCore.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component")); } this.Core.IndexElement(row, urlReservation); } }
/// <summary> /// Mutate the Component elements. /// </summary> private void MutateComponents() { if (this.setUniqueIdentifiers) { IdentifierGenerator identifierGenerator = new IdentifierGenerator("Component"); // index all the existing identifiers foreach (Wix.Component component in this.components) { if (null != component.Id) { identifierGenerator.IndexExistingIdentifier(component.Id); } } // index all the web site identifiers foreach (IIs.WebSite webSite in this.webSites) { if (webSite.ParentElement is Wix.Component) { identifierGenerator.IndexName(webSite.Id); } } // create an identifier for each component based on its child web site identifier foreach (IIs.WebSite webSite in this.webSites) { Wix.Component component = webSite.ParentElement as Wix.Component; if (null != component) { component.Id = identifierGenerator.GetIdentifier(webSite.Id); } } } }
/// <summary> /// Creates the shim component. /// </summary> /// <returns>Component for the shim.</returns> private Wix.Component GenerateShimComponent() { Wix.Component shimComponent = new Wix.Component(); if (Guid.Empty == this.shimGuid) { this.shimGuid = Guid.NewGuid(); } shimComponent.Id = "ThisApplicationShimDllComponent"; shimComponent.Guid = this.shimGuid.ToString("B"); Wix.File file = new Wix.File(); file.Id = "ThisApplicationShimDll"; file.Name = String.Concat(Path.GetFileNameWithoutExtension(this.entryFileRelativePath), "Shim.dll"); file.Vital = Wix.YesNoType.yes; file.KeyPath = Wix.YesNoType.yes; file.Source = this.shimPath; shimComponent.AddChild(file); // Add the CLSID and ProgId to the component. Wix.Class classId = new Wix.Class(); classId.Id = this.ShimClsid.ToString("B"); classId.Context = Wix.Class.ContextType.InprocServer32; if (null != this.Description && String.Empty != this.Description) { classId.Description = this.Description; } classId.ThreadingModel = Wix.Class.ThreadingModelType.apartment; file.AddChild(classId); Wix.ProgId progId = new Wix.ProgId(); progId.Id = this.ShimProgid; progId.Description = "Connect Class"; classId.AddChild(progId); // Add the Addin to the extended Office applications. foreach (OfficeAddinFabricator.OfficeApplications extendedOfficeApp in this.extendedOfficeApplications) { Wix.RegistryKey registryKey = new Wix.RegistryKey(); registryKey.Root = Wix.RegistryRootType.HKMU; registryKey.Key = String.Format("Software\\Microsoft\\Office\\{0}\\Addins\\{1}", OfficeAddinFabricator.OfficeApplicationStrings[(int)extendedOfficeApp], this.ShimProgid); shimComponent.AddChild(registryKey); Wix.RegistryValue registryValue = new Wix.RegistryValue(); registryValue.Name = "Description"; registryValue.Value = "[ProductName] v[ProductVersion]"; registryValue.Type = Wix.RegistryValue.TypeType.@string; registryKey.AddChild(registryValue); registryValue = new Wix.RegistryValue(); registryValue.Name = "FriendlyName"; registryValue.Value = "[ProductName]"; registryValue.Type = Wix.RegistryValue.TypeType.@string; registryKey.AddChild(registryValue); registryValue = new Wix.RegistryValue(); registryValue.Name = "LoadBehavior"; registryValue.Value = "3"; registryValue.Type = Wix.RegistryValue.TypeType.integer; registryKey.AddChild(registryValue); } return shimComponent; }
/// <summary> /// Creates a component group with a given name. /// </summary> /// <param name="wix">The Wix document element.</param> private void CreateComponentGroup(Wix.Wix wix) { Wix.ComponentGroup componentGroup = new Wix.ComponentGroup(); componentGroup.Id = this.componentGroupName; this.componentGroups.Add(componentGroup); Wix.Fragment cgFragment = new Wix.Fragment(); cgFragment.AddChild(componentGroup); wix.AddChild(cgFragment); int componentCount = 0; for (; componentCount < this.components.Count; componentCount++) { Wix.Component c = this.components[componentCount] as Wix.Component; if (this.createFragments) { if (c.ParentElement is Wix.Directory) { Wix.Directory parentDirectory = c.ParentElement as Wix.Directory; componentGroup.AddChild(c); c.Directory = parentDirectory.Id; parentDirectory.RemoveChild(c); } else if (c.ParentElement is Wix.DirectoryRef) { Wix.DirectoryRef parentDirectory = c.ParentElement as Wix.DirectoryRef; componentGroup.AddChild(c); c.Directory = parentDirectory.Id; parentDirectory.RemoveChild(c); // Remove whole fragment if moving the component to the component group just leaves an empty DirectoryRef if (0 < fragments.Count && parentDirectory.ParentElement is Wix.Fragment) { Wix.Fragment parentFragment = parentDirectory.ParentElement as Wix.Fragment; int childCount = 0; foreach (Wix.ISchemaElement element in parentFragment.Children) { childCount++; } // Component should always have an Id but the SortedList creation allows for null and bases the name on the fragment count which we cannot reverse engineer here. if (1 == childCount && !String.IsNullOrEmpty(c.Id)) { int removeIndex = fragments.IndexOfKey(String.Concat("Component:", c.Id)); if (0 <= removeIndex) { fragments.RemoveAt(removeIndex); } } } } } else { Wix.ComponentRef componentRef = new Wix.ComponentRef(); componentRef.Id = c.Id; componentGroup.AddChild(componentRef); } } }
/// <summary> /// Converts the registry values to WiX regisry key element. /// </summary> /// <param name="sr">The registry file stream.</param> /// <param name="component">A WiX component reference.</param> /// <param name="root">The root key.</param> /// <param name="line">The current line.</param> private void ConvertValues(StreamReader sr, ref Wix.Component component, Wix.RegistryRootType root, string line) { string name = null; string value = null; Wix.RegistryValue.TypeType type; Wix.RegistryKey registryKey = new Wix.RegistryKey(); registryKey.Root = root; registryKey.Key = line; while (this.GetValue(sr, ref name, ref value, out type)) { Wix.RegistryValue registryValue = new Wix.RegistryValue(); ArrayList charArray; // Don't specifiy name for default attribute if (!string.IsNullOrEmpty(name)) { registryValue.Name = name; } registryValue.Type = type; switch (type) { case Wix.RegistryValue.TypeType.binary: registryValue.Value = value.Replace(",", string.Empty).ToUpper(); break; case Wix.RegistryValue.TypeType.integer: registryValue.Value = Int32.Parse(value, NumberStyles.HexNumber).ToString(); break; case Wix.RegistryValue.TypeType.expandable: charArray = this.ConvertCharList(value); value = string.Empty; // create the string, remove the terminating null for (int i = 0; i < charArray.Count; i++) { if ('\0' != (char)charArray[i]) { value += charArray[i]; } } registryValue.Value = value; break; case Wix.RegistryValue.TypeType.multiString: charArray = this.ConvertCharList(value); value = string.Empty; // Convert the character array to a string so we can simply split it at the nulls, ignore the final null null. for (int i = 0; i < (charArray.Count - 2); i++) { value += charArray[i]; } // Although the value can use [~] the preffered way is to use MultiStringValue string[] parts = value.Split("\0".ToCharArray()); foreach (string part in parts) { Wix.MultiStringValue multiStringValue = new Wix.MultiStringValue(); multiStringValue.Content = part; registryValue.AddChild(multiStringValue); } break; case Wix.RegistryValue.TypeType.@string: // Remove \\ and \" value = value.ToString().Replace("\\\"", "\""); value = value.ToString().Replace(@"\\", @"\"); // Escape [ and ] value = value.ToString().Replace(@"[", @"[\[]"); value = value.ToString().Replace(@"]", @"[\]]"); // This undoes the duplicate escaping caused by the second replace value = value.ToString().Replace(@"[\[[\]]", @"[\[]"); // Escape $ value = value.ToString().Replace(@"$", @"$$"); registryValue.Value = value; break; default: throw new ApplicationException(String.Format("Did not recognize the type of reg value on line {0}", this.currentLineNumber)); } registryKey.AddChild(registryValue); } // Make sure empty keys are created if (null == value) { registryKey.ForceCreateOnInstall = Wix.YesNoType.yes; } component.AddChild(registryKey); }
/// <summary> /// Builds a setup package to the specified output path. /// </summary> /// <param name="outputPath">Location to build the setup package to.</param> /// <param name="outputSourcePath">Optional path where the package's .wxs file will be written.</param> public bool Build(string outputPath, string outputSourcePath) { this.buildError = null; // clear out any previous errors int currentProgress = 0; int totalProgress = 7; // calculate the upper progress if (outputSourcePath != null) { ++totalProgress; } if (this.previousPackagePath != null) { ++totalProgress; } this.VerifyRequiredInformation(); if (!this.OnProgress(currentProgress++, totalProgress, "Initialized package builder...")) { return false; } // Calculate where everything is going string localSetupExe = outputPath; string localSetupFeed = Path.Combine(Path.GetDirectoryName(outputPath), Path.GetFileName(this.updateUrl.AbsolutePath)); Uri urlSetupExe = new Uri(this.updateUrl, Path.GetFileName(localSetupExe)); Uri urlSetupFeed = new Uri(this.updateUrl, Path.GetFileName(localSetupFeed)); Guid previousUpgradeCode = Guid.Empty; Version previousVersion = null; Uri previousSetupFeed = null; // if a previous package was provided, go read the key information out of it now if (this.previousPackagePath != null) { if (!this.OnProgress(currentProgress++, totalProgress, "Reading previous package...")) { return false; } this.ReadPreviousPackage(this.previousPackagePath, out previousUpgradeCode, out previousVersion, out previousSetupFeed); } // // if a upgrade code and/or version has not been specified use one // from the previous package or create new. // if (this.upgradeCode == Guid.Empty) { if (previousUpgradeCode == Guid.Empty) { this.upgradeCode = Guid.NewGuid(); } else { this.upgradeCode = previousUpgradeCode; } } if (this.version == null) { if (previousVersion == null) { FileVersionInfo fileVersionInfo = FileVersionInfo.GetVersionInfo(Path.Combine(this.applicationRoot.Content, this.applicationEntry.Content)); this.version = new Version(fileVersionInfo.FileVersion); } else { this.version = previousVersion; } } // verify that new data is okay when compared to previous package if (previousUpgradeCode != Guid.Empty && previousUpgradeCode != this.upgradeCode) { this.OnMessage(ClickThroughErrors.UpgradeCodeChanged(previousUpgradeCode, this.upgradeCode)); } if (previousVersion != null && previousVersion >= this.version) { this.OnMessage(ClickThroughErrors.NewVersionIsNotGreater(previousVersion, this.version)); } if (this.buildError != null) { throw new InvalidOperationException(String.Format(this.buildError.ResourceManager.GetString(this.buildError.ResourceName), this.buildError.MessageArgs)); } else if (!this.OnProgress(currentProgress++, totalProgress, "Processing package information...")) { return false; } // Product information Application application = new Application(); application.Product.Id = Guid.NewGuid().ToString(); application.Product.Language = "1033"; application.Product.Manufacturer = this.manufacturerName.Content; application.Product.Name = this.applicationName.Content; application.Package.Description = this.description.Content; application.Product.UpgradeCode = this.upgradeCode.ToString(); application.Product.Version = this.version.ToString(); Wix.WixVariable variable = new Wix.WixVariable(); variable = new Wix.WixVariable(); variable.Id = "ProductName"; variable.Value = application.Product.Name; application.Product.AddChild(variable); variable = new Wix.WixVariable(); variable.Id = "ProductCode"; variable.Value = application.Product.Id; application.Product.AddChild(variable); variable = new Wix.WixVariable(); variable.Id = "ProductVersion"; variable.Value = application.Product.Version; application.Product.AddChild(variable); variable = new Wix.WixVariable(); variable.Id = "ShortcutFileId"; variable.Value = "todoFileIdHere"; application.Product.AddChild(variable); // Upgrade logic Wix.Upgrade upgrade = new Wix.Upgrade(); upgrade.Id = application.Product.UpgradeCode; application.Product.AddChild(upgrade); Wix.UpgradeVersion minUpgrade = new Wix.UpgradeVersion(); minUpgrade.Minimum = application.Product.Version; minUpgrade.OnlyDetect = Wix.YesNoType.yes; minUpgrade.Property = "NEWERVERSIONDETECTED"; upgrade.AddChild(minUpgrade); Wix.UpgradeVersion maxUpgrade = new Wix.UpgradeVersion(); maxUpgrade.Maximum = application.Product.Version; maxUpgrade.IncludeMaximum = Wix.YesNoType.no; maxUpgrade.Property = "OLDERVERSIONBEINGUPGRADED"; upgrade.AddChild(maxUpgrade); // Update Feed Wix.Property property = new Wix.Property(); property.Id = "ARPURLUPDATEINFO"; property.Value = urlSetupFeed.AbsoluteUri; application.Product.AddChild(property); #if false // Directory tree Wix.DirectoryRef applicationCacheRef = new Wix.DirectoryRef(); applicationCacheRef.Id = "ApplicationsCacheFolder"; application.Product.AddChild(applicationCacheRef); #endif Wix.DirectoryRef directoryRef = new Wix.DirectoryRef(); directoryRef.Id = "ApplicationsFolder"; application.Product.AddChild(directoryRef); this.applicationRootDirectory.Name = String.Concat(application.Product.UpgradeCode, "v", application.Product.Version); directoryRef.AddChild(this.applicationRootDirectory); #if false // System registry keys Wix.Component registryComponent = new Wix.Component(); registryComponent.Id = "SystemVersionRegistryKeyComponent"; registryComponent.Guid = Guid.NewGuid().ToString(); directoryRef.AddChild(registryComponent); Wix.Registry productRegKey = new Wix.Registry(); productRegKey.Root = Wix.RegistryRootType.HKCU; productRegKey.Key = @"Software\WiX\ClickThrough\Applications\[UpgradeCode]"; productRegKey.Action = Wix.Registry.ActionType.createKeyAndRemoveKeyOnUninstall; registryComponent.AddChild(productRegKey); Wix.Registry versionRegKey = new Wix.Registry(); versionRegKey.Name = "Version"; versionRegKey.Type = Wix.Registry.TypeType.@string; versionRegKey.Value = "[ProductVersion]"; productRegKey.AddChild(versionRegKey); Wix.Registry sourceRegKey = new Wix.Registry(); sourceRegKey.Name = "UpdateInfoSource"; sourceRegKey.Type = Wix.Registry.TypeType.@string; sourceRegKey.Value = "[ARPURLUPDATEINFO]"; productRegKey.AddChild(sourceRegKey); // Shortcut Wix.DirectoryRef programMenuRef = new Wix.DirectoryRef(); programMenuRef.Id = "ProgramMenuFolder"; Wix.Directory shortcutsDirectory = new Wix.Directory(); shortcutsDirectory.Id = "ThisAppShortcuts"; shortcutsDirectory.LongName = application.Product.Name; shortcutsDirectory.Name = "AppSCDir"; programMenuRef.AddChild(shortcutsDirectory); application.Product.AddChild(programMenuRef); Wix.Component shortcutsComponent = new Wix.Component(); shortcutsComponent.Id = "ThisApplicationShortcutComponent"; shortcutsComponent.Guid = Guid.NewGuid().ToString(); shortcutsComponent.KeyPath = Wix.YesNoType.yes; shortcutsDirectory.AddChild(shortcutsComponent); Wix.CreateFolder shortcutsCreateFolder = new Wix.CreateFolder(); shortcutsComponent.AddChild(shortcutsCreateFolder); Wix.Shortcut shortcut = this.GetShortcut(this.applicationEntry.Content, rootDirectory, shortcutsDirectory); shortcutsComponent.AddChild(shortcut); // Remove cached MSI file. Wix.Component removeComponent = new Wix.Component(); removeComponent.Id = "ThisApplicationRemoveComponent"; removeComponent.Guid = Guid.NewGuid().ToString(); removeComponent.KeyPath = Wix.YesNoType.yes; applicationCacheRef.AddChild(removeComponent); Wix.RemoveFile cacheRemoveFile = new Wix.RemoveFile(); cacheRemoveFile.Id = "ThisApplicationRemoveCachedMsi"; cacheRemoveFile.Directory = "ApplicationsCacheFolder"; cacheRemoveFile.Name = "unknown.msi"; cacheRemoveFile.LongName = String.Concat("{", application.Product.Id.ToUpper(CultureInfo.InvariantCulture), "}v", application.Version.ToString(), ".msi"); cacheRemoveFile.On = Wix.RemoveFile.OnType.uninstall; removeComponent.AddChild(cacheRemoveFile); Wix.RemoveFile cacheRemoveFolder = new Wix.RemoveFile(); cacheRemoveFolder.Id = "ThisApplicationRemoveCacheFolder"; cacheRemoveFolder.Directory = "ApplicationsCacheFolder"; cacheRemoveFolder.On = Wix.RemoveFile.OnType.uninstall; removeComponent.AddChild(cacheRemoveFolder); Wix.RemoveFile applicationRemoveFolder = new Wix.RemoveFile(); applicationRemoveFolder.Id = "ThisApplicationRemoveApplicationsFolder"; applicationRemoveFolder.Directory = "ApplicationsFolder"; applicationRemoveFolder.On = Wix.RemoveFile.OnType.uninstall; removeComponent.AddChild(applicationRemoveFolder); #endif // Feature tree Wix.FeatureRef applicationFeatureRef = new Wix.FeatureRef(); applicationFeatureRef.Id = "ApplicationFeature"; application.Product.AddChild(applicationFeatureRef); #if false Wix.Feature applicationFeature = new Wix.Feature(); applicationFeature.Id = "ApplicationFeature"; applicationFeature.Display = "expand"; applicationFeature.Level = 1; applicationFeature.Absent = Wix.Feature.AbsentType.disallow; applicationFeature.AllowAdvertise = Wix.Feature.AllowAdvertiseType.yes; applicationFeature.InstallDefault = Wix.Feature.InstallDefaultType.local; applicationFeature.TypicalDefault = Wix.Feature.TypicalDefaultType.install; application.Product.AddChild(applicationFeature); Wix.ComponentRef shortcutsComponentRef = new Wix.ComponentRef(); shortcutsComponentRef.Id = shortcutsComponent.Id; applicationFeature.AddChild(shortcutsComponentRef); Wix.ComponentRef removeComponentRef = new Wix.ComponentRef(); removeComponentRef.Id = removeComponent.Id; applicationFeature.AddChild(removeComponentRef); #endif Wix.ComponentRef[] componentRefs = this.GetComponentRefs(this.applicationRootDirectory); foreach (Wix.ComponentRef componentRef in componentRefs) { applicationFeatureRef.AddChild(componentRef); } if (!this.OnProgress(currentProgress++, totalProgress, "Serializing package information into XML...")) { return false; } // serialize to an xml string string xml; using (StringWriter sw = new StringWriter()) { XmlTextWriter writer = null; try { writer = new XmlTextWriter(sw); application.WixRoot.OutputXml(writer); xml = sw.ToString(); } finally { if (writer != null) { writer.Close(); } } } // load the xml into a document XmlDocument sourceDoc = new XmlDocument(); sourceDoc.LoadXml(xml); if (outputSourcePath != null) { if (!this.OnProgress(currentProgress++, totalProgress, "Saving .wxs file...")) { return false; } sourceDoc.Save(outputSourcePath); } // generate the MSI, create the setup.exe, and generate the RSS feed. string outputMsi = null; try { outputMsi = Path.GetTempFileName(); if (!this.OnProgress(currentProgress++, totalProgress, "Generating .msi file...")) { return false; } this.GenerateMsi(sourceDoc, outputMsi); if (this.buildError != null) { throw new InvalidOperationException(String.Format(this.buildError.ResourceManager.GetString(this.buildError.ResourceName), this.buildError.MessageArgs)); } string assemblyPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); if (!this.OnProgress(currentProgress++, totalProgress, "Generating setup bootstrapper...")) { return false; } /* NativeMethods.CREATE_SETUP_PACKAGE[] createSetup = new Microsoft.Tools.WindowsInstallerXml.ClickThrough.NativeMethods.CREATE_SETUP_PACKAGE[1]; createSetup[0].fPrivileged = false; createSetup[0].fCache = true; createSetup[0].wzSourcePath = outputMsi; int hr = NativeMethods.CreateSetup(Path.Combine(assemblyPath, "setup.exe"), createSetup, createSetup.Length, localSetupExe); */ int hr = NativeMethods.CreateSimpleSetup(Path.Combine(assemblyPath, "setup.exe"), outputMsi, localSetupExe); if (hr != 0) { this.OnMessage(ClickThroughErrors.FailedSetupExeCreation(Path.Combine(assemblyPath, "setup.exe"), localSetupExe)); } if (!this.OnProgress(currentProgress++, totalProgress, "Generating update feed...")) { return false; } this.GenerateRssFeed(localSetupFeed, localSetupExe, urlSetupExe, application.Product.Id, application.Product.UpgradeCode, application.Product.Version); } finally { this.OnProgress(currentProgress++, totalProgress, "Cleaning up..."); if (outputMsi != null) { File.Delete(outputMsi); } } if (this.buildError != null) { throw new InvalidOperationException(String.Format(this.buildError.ResourceManager.GetString(this.buildError.ResourceName), this.buildError.MessageArgs)); } else if (!this.OnProgress(currentProgress++, totalProgress, "Package build complete.")) { return false; } return true; }
/// <summary> /// Decompile the MessageQueue table. /// </summary> /// <param name="table">The table to decompile.</param> private void DecompileMessageQueueTable(Table table) { foreach (Row row in table.Rows) { Msmq.MessageQueue queue = new Msmq.MessageQueue(); queue.Id = (string)row[0]; if (null != row[2]) { queue.BasePriority = (int)row[2]; } if (null != row[3]) { queue.JournalQuota = (int)row[3]; } queue.Label = (string)row[4]; if (null != row[5]) { queue.MulticastAddress = (string)row[5]; } queue.PathName = (string)row[6]; if (null != row[7]) { switch ((MsmqCompiler.MqiMessageQueuePrivacyLevel)row[7]) { case MsmqCompiler.MqiMessageQueuePrivacyLevel.None: queue.PrivLevel = Msmq.MessageQueue.PrivLevelType.none; break; case MsmqCompiler.MqiMessageQueuePrivacyLevel.Optional: queue.PrivLevel = Msmq.MessageQueue.PrivLevelType.optional; break; case MsmqCompiler.MqiMessageQueuePrivacyLevel.Body: queue.PrivLevel = Msmq.MessageQueue.PrivLevelType.body; break; default: break; } } if (null != row[8]) { queue.Quota = (int)row[8]; } if (null != row[9]) { queue.ServiceTypeGuid = (string)row[9]; } int attributes = (int)row[10]; if (0 != (attributes & (int)MsmqCompiler.MqiMessageQueueAttributes.Authenticate)) { queue.Authenticate = Msmq.YesNoType.yes; } if (0 != (attributes & (int)MsmqCompiler.MqiMessageQueueAttributes.Journal)) { queue.Journal = Msmq.YesNoType.yes; } if (0 != (attributes & (int)MsmqCompiler.MqiMessageQueueAttributes.Transactional)) { queue.Transactional = Msmq.YesNoType.yes; } Wix.Component component = (Wix.Component) this.Core.GetIndexedElement("Component", (string)row[1]); if (null != component) { component.AddChild(queue); } else { this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerCore.PrimaryKeyDelimiter), "Component_", (string)row[1], "Component")); } } }
/// <summary> /// Harvest files from one output group of a VS project. /// </summary> /// <param name="baseDir">The base directory of the files.</param> /// <param name="projectName">Name of the project, to be used as a prefix for generated identifiers.</param> /// <param name="pogName">Name of the project output group, used for generating identifiers for WiX elements.</param> /// <param name="pogFileSource">The ProjectOutputGroup file source.</param> /// <param name="outputGroupFiles">The files from one output group to harvest.</param> /// <param name="parent">The parent element that will contain the components of the harvested files.</param> /// <returns>The number of files harvested.</returns> private int HarvestProjectOutputGroupFiles(string baseDir, string projectName, string pogName, string pogFileSource, IEnumerable outputGroupFiles, Wix.IParentElement parent) { int fileCount = 0; Wix.ISchemaElement exeFile = null; Wix.ISchemaElement appConfigFile = null; // Keep track of files inserted // Files can have different absolute paths but get mapped to the same SourceFile // after the project variables have been used. For example, a WiX project that // is building multiple cultures will have many output MSIs/MSMs, but will all get // mapped to $(var.ProjName.TargetDir)\ProjName.msm. These duplicates would // prevent generated code from compiling. Dictionary<string, bool> seenList = new Dictionary<string,bool>(); foreach (object output in outputGroupFiles) { string filePath = output.ToString(); string fileName = Path.GetFileName(filePath); string fileDir = Path.GetDirectoryName(filePath); string link = null; MethodInfo getMetadataMethod = output.GetType().GetMethod("GetMetadata"); if (getMetadataMethod != null) { link = (string)getMetadataMethod.Invoke(output, new object[] { "Link" }); if (!String.IsNullOrEmpty(link)) { fileDir = Path.GetDirectoryName(Path.Combine(baseDir, link)); } } Wix.IParentElement parentDir = parent; // Ignore Containers and PayloadGroups because they do not have a nested structure. if (baseDir != null && !String.Equals(Path.GetDirectoryName(baseDir), fileDir, StringComparison.OrdinalIgnoreCase) && this.GenerateType != GenerateType.Container && this.GenerateType != GenerateType.PackageGroup && this.GenerateType != GenerateType.PayloadGroup) { Uri baseUri = new Uri(baseDir); Uri relativeUri = baseUri.MakeRelativeUri(new Uri(fileDir)); parentDir = this.GetSubDirElement(parentDir, relativeUri); } string parentDirId = null; if (parentDir is Wix.DirectoryRef) { parentDirId = this.directoryRefSeed; } else if (parentDir is Wix.Directory) { parentDirId = ((Wix.Directory)parentDir).Id; } if (this.GenerateType == GenerateType.Container || this.GenerateType == GenerateType.PayloadGroup) { Wix.Payload payload = new Wix.Payload(); HarvestProjectOutputGroupPayloadFile(baseDir, projectName, pogName, pogFileSource, filePath, fileName, link, parentDir, payload, seenList); } else if (this.GenerateType == GenerateType.PackageGroup) { HarvestProjectOutputGroupPackage(projectName, pogName, pogFileSource, filePath, fileName, link, parentDir, seenList); } else { Wix.Component component = new Wix.Component(); Wix.File file = new Wix.File(); HarvestProjectOutputGroupFile(baseDir, projectName, pogName, pogFileSource, filePath, fileName, link, parentDir, parentDirId, component, file, seenList); if (String.Equals(Path.GetExtension(file.Source), ".exe", StringComparison.OrdinalIgnoreCase)) { exeFile = file; } else if (file.Source.EndsWith("app.config", StringComparison.OrdinalIgnoreCase)) { appConfigFile = file; } } fileCount++; } // Special case for the app.config file in the Binaries POG... // The POG refers to the files in the OBJ directory, while the // generated WiX code references them in the bin directory. // The app.config file gets renamed to match the exe name. if ("Binaries" == pogName && null != exeFile && null != appConfigFile) { if (appConfigFile is Wix.File) { Wix.File appConfigFileAsWixFile = appConfigFile as Wix.File; Wix.File exeFileAsWixFile = exeFile as Wix.File; // Case insensitive replace appConfigFileAsWixFile.Source = Regex.Replace(appConfigFileAsWixFile.Source, @"app\.config", Path.GetFileName(exeFileAsWixFile.Source) + ".config", RegexOptions.IgnoreCase); } } return fileCount; }
/// <summary> /// Decompile the Component table. /// </summary> /// <param name="table">The table to decompile.</param> private void DecompileComponentTable(Table table) { foreach (Row row in table.Rows) { Wix.Component component = new Wix.Component(); component.Id = Convert.ToString(row[0]); component.Guid = Convert.ToString(row[1]); int attributes = Convert.ToInt32(row[3]); if (MsiInterop.MsidbComponentAttributesSourceOnly == (attributes & MsiInterop.MsidbComponentAttributesSourceOnly)) { component.Location = Wix.Component.LocationType.source; } else if (MsiInterop.MsidbComponentAttributesOptional == (attributes & MsiInterop.MsidbComponentAttributesOptional)) { component.Location = Wix.Component.LocationType.either; } if (MsiInterop.MsidbComponentAttributesSharedDllRefCount == (attributes & MsiInterop.MsidbComponentAttributesSharedDllRefCount)) { component.SharedDllRefCount = Wix.YesNoType.yes; } if (MsiInterop.MsidbComponentAttributesPermanent == (attributes & MsiInterop.MsidbComponentAttributesPermanent)) { component.Permanent = Wix.YesNoType.yes; } if (MsiInterop.MsidbComponentAttributesTransitive == (attributes & MsiInterop.MsidbComponentAttributesTransitive)) { component.Transitive = Wix.YesNoType.yes; } if (MsiInterop.MsidbComponentAttributesNeverOverwrite == (attributes & MsiInterop.MsidbComponentAttributesNeverOverwrite)) { component.NeverOverwrite = Wix.YesNoType.yes; } if (MsiInterop.MsidbComponentAttributes64bit == (attributes & MsiInterop.MsidbComponentAttributes64bit)) { component.Win64 = Wix.YesNoType.yes; } if (MsiInterop.MsidbComponentAttributesDisableRegistryReflection == (attributes & MsiInterop.MsidbComponentAttributesDisableRegistryReflection)) { component.DisableRegistryReflection = Wix.YesNoType.yes; } if (MsiInterop.MsidbComponentAttributesUninstallOnSupersedence == (attributes & MsiInterop.MsidbComponentAttributesUninstallOnSupersedence)) { component.UninstallWhenSuperseded = Wix.YesNoType.yes; } if (MsiInterop.MsidbComponentAttributesShared == (attributes & MsiInterop.MsidbComponentAttributesShared)) { component.Shared = Wix.YesNoType.yes; } if (null != row[4]) { Wix.Condition condition = new Wix.Condition(); condition.Content = Convert.ToString(row[4]); component.AddChild(condition); } Wix.Directory directory = (Wix.Directory)this.core.GetIndexedElement("Directory", Convert.ToString(row[2])); if (null != directory) { directory.AddChild(component); } else { this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerCore.PrimaryKeyDelimiter), "Directory_", Convert.ToString(row[2]), "Directory")); } this.core.IndexElement(row, component); } }
/// <summary> /// Decompile the SqlDatabase table. /// </summary> /// <param name="table">The table to decompile.</param> private void DecompileSqlDatabaseTable(Table table) { foreach (Row row in table.Rows) { Sql.SqlDatabase sqlDatabase = new Sql.SqlDatabase(); sqlDatabase.Id = (string)row[0]; if (null != row[1]) { sqlDatabase.Server = (string)row[1]; } if (null != row[2]) { sqlDatabase.Instance = (string)row[2]; } sqlDatabase.Database = (string)row[3]; if (null != row[5]) { sqlDatabase.User = (string)row[5]; } // the FileSpec_ and FileSpec_Log columns will be handled in FinalizeSqlFileSpecTable if (null != row[8]) { int attributes = (int)row[8]; if (SqlCompiler.DbCreateOnInstall == (attributes & SqlCompiler.DbCreateOnInstall)) { sqlDatabase.CreateOnInstall = Sql.YesNoType.yes; } if (SqlCompiler.DbDropOnUninstall == (attributes & SqlCompiler.DbDropOnUninstall)) { sqlDatabase.DropOnUninstall = Sql.YesNoType.yes; } if (SqlCompiler.DbContinueOnError == (attributes & SqlCompiler.DbContinueOnError)) { sqlDatabase.ContinueOnError = Sql.YesNoType.yes; } if (SqlCompiler.DbDropOnInstall == (attributes & SqlCompiler.DbDropOnInstall)) { sqlDatabase.DropOnInstall = Sql.YesNoType.yes; } if (SqlCompiler.DbCreateOnUninstall == (attributes & SqlCompiler.DbCreateOnUninstall)) { sqlDatabase.CreateOnUninstall = Sql.YesNoType.yes; } if (SqlCompiler.DbConfirmOverwrite == (attributes & SqlCompiler.DbConfirmOverwrite)) { sqlDatabase.ConfirmOverwrite = Sql.YesNoType.yes; } if (SqlCompiler.DbCreateOnReinstall == (attributes & SqlCompiler.DbCreateOnReinstall)) { sqlDatabase.CreateOnReinstall = Sql.YesNoType.yes; } if (SqlCompiler.DbDropOnReinstall == (attributes & SqlCompiler.DbDropOnReinstall)) { sqlDatabase.DropOnReinstall = Sql.YesNoType.yes; } } if (null != row[4]) { Wix.Component component = (Wix.Component) this.Core.GetIndexedElement("Component", (string)row[4]); if (null != component) { component.AddChild(sqlDatabase); } else { this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerCore.PrimaryKeyDelimiter), "Component_", (string)row[4], "Component")); } } else { this.Core.RootElement.AddChild(sqlDatabase); } this.Core.IndexElement(row, sqlDatabase); } }
/// <summary> /// Finalize the SqlScript table. /// </summary> /// <param name="tables">The collection of all tables.</param> /// <remarks> /// The SqlScript and SqlString tables contain a foreign key into the SqlDatabase /// and Component tables. Depending upon the parent of the SqlDatabase /// element, the SqlScript and SqlString elements are nested under either the /// SqlDatabase or the Component element. /// </remarks> private void FinalizeSqlScriptAndSqlStringTables(TableCollection tables) { Table sqlDatabaseTable = tables["SqlDatabase"]; Table sqlScriptTable = tables["SqlScript"]; Table sqlStringTable = tables["SqlString"]; Hashtable sqlDatabaseRows = new Hashtable(); // index each SqlDatabase row by its primary key if (null != sqlDatabaseTable) { foreach (Row row in sqlDatabaseTable.Rows) { sqlDatabaseRows.Add(row[0], row); } } if (null != sqlScriptTable) { foreach (Row row in sqlScriptTable.Rows) { Sql.SqlScript sqlScript = (Sql.SqlScript) this.Core.GetIndexedElement(row); Row sqlDatabaseRow = (Row)sqlDatabaseRows[row[1]]; string databaseComponent = (string)sqlDatabaseRow[4]; // determine if the SqlScript element should be nested under the database or another component if (null != databaseComponent && databaseComponent == (string)row[2]) { Sql.SqlDatabase sqlDatabase = (Sql.SqlDatabase) this.Core.GetIndexedElement(sqlDatabaseRow); sqlDatabase.AddChild(sqlScript); } else // nest under the component of the SqlDatabase row { Wix.Component component = (Wix.Component) this.Core.GetIndexedElement("Component", (string)row[2]); // set the Database value sqlScript.SqlDb = (string)row[1]; if (null != component) { component.AddChild(sqlScript); } else { this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, sqlScriptTable.Name, row.GetPrimaryKey(DecompilerCore.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component")); } } } } if (null != sqlStringTable) { foreach (Row row in sqlStringTable.Rows) { Sql.SqlString sqlString = (Sql.SqlString) this.Core.GetIndexedElement(row); Row sqlDatabaseRow = (Row)sqlDatabaseRows[row[1]]; string databaseComponent = (string)sqlDatabaseRow[4]; // determine if the SqlScript element should be nested under the database or another component if (null != databaseComponent && databaseComponent == (string)row[2]) { Sql.SqlDatabase sqlDatabase = (Sql.SqlDatabase) this.Core.GetIndexedElement(sqlDatabaseRow); sqlDatabase.AddChild(sqlString); } else // nest under the component of the SqlDatabase row { Wix.Component component = (Wix.Component) this.Core.GetIndexedElement("Component", (string)row[2]); // set the Database value sqlString.SqlDb = (string)row[1]; if (null != component) { component.AddChild(sqlString); } else { this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, sqlStringTable.Name, row.GetPrimaryKey(DecompilerCore.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component")); } } } } }
/// <summary> /// Harvest a directory. /// </summary> /// <param name="path">The path of the directory.</param> /// <param name="relativePath">The relative path that will be used when harvesting.</param> /// <param name="directory">The directory for this path.</param> /// <returns>The number of files harvested.</returns> private int HarvestDirectory(string path, string relativePath, Wix.Directory directory) { int fileCount = 0; // harvest the child directories foreach (string childDirectoryPath in Directory.GetDirectories(path)) { Wix.Directory childDirectory = new Wix.Directory(); childDirectory.Name = Path.GetFileName(childDirectoryPath); childDirectory.FileSource = childDirectoryPath; if (this.setUniqueIdentifiers) { childDirectory.Id = this.Core.GenerateIdentifier(DirectoryPrefix, directory.Id, childDirectory.Name); } int childFileCount = this.HarvestDirectory(childDirectoryPath, String.Concat(relativePath, childDirectory.Name, "\\"), childDirectory); // keep the directory if it contained any files (or empty directories are being kept) if (0 < childFileCount || this.keepEmptyDirectories) { directory.AddChild(childDirectory); } fileCount += childFileCount; } // harvest the files string[] files = Directory.GetFiles(path); if (0 < files.Length) { foreach (string filePath in Directory.GetFiles(path)) { string fileName = Path.GetFileName(filePath); Wix.Component component = new Wix.Component(); Wix.File file = this.fileHarvester.HarvestFile(filePath); file.Source = String.Concat(relativePath, fileName); if (this.setUniqueIdentifiers) { file.Id = this.Core.GenerateIdentifier(FilePrefix, directory.Id, fileName); component.Id = this.Core.GenerateIdentifier(ComponentPrefix, directory.Id, file.Id); } component.AddChild(file); directory.AddChild(component); } } else if (0 == fileCount && this.keepEmptyDirectories) { Wix.Component component = new Wix.Component(); component.KeyPath = Wix.YesNoType.yes; if (this.setUniqueIdentifiers) { component.Id = this.Core.GenerateIdentifier(ComponentPrefix, directory.Id); } Wix.CreateFolder createFolder = new Wix.CreateFolder(); component.AddChild(createFolder); directory.AddChild(component); } return fileCount + files.Length; }
/// <summary> /// Harvest a file. /// </summary> /// <param name="argument">The path of the file.</param> /// <returns>A harvested file.</returns> public override Wix.Fragment[] Harvest(string argument) { if (null == argument) { throw new ArgumentNullException("argument"); } if (null == this.rootedDirectoryRef) { this.rootedDirectoryRef = "TARGETDIR"; } string fullPath = Path.GetFullPath(argument); Wix.DirectoryRef directoryRef = new Wix.DirectoryRef(); directoryRef.Id = this.rootedDirectoryRef; Wix.File file = this.HarvestFile(fullPath); if (!this.suppressRootDirectory) { file.Source = String.Concat("SourceDir\\", Path.GetFileName(Path.GetDirectoryName(fullPath)), "\\", Path.GetFileName(fullPath)); } Wix.Component component = new Wix.Component(); component.AddChild(file); Wix.Directory directory = new Wix.Directory(); if (this.suppressRootDirectory) { directoryRef.AddChild(component); } else { string directoryPath = Path.GetDirectoryName(Path.GetFullPath(argument)); directory.Name = Path.GetFileName(directoryPath); if (this.setUniqueIdentifiers) { directory.Id = this.Core.GenerateIdentifier(DirectoryPrefix, directoryRef.Id, directory.Name); } directory.AddChild(component); directoryRef.AddChild(directory); } if (this.setUniqueIdentifiers) { file.Id = this.Core.GenerateIdentifier(FilePrefix, (this.suppressRootDirectory) ? directoryRef.Id : directory.Id, Path.GetFileName(file.Source)); component.Id = this.Core.GenerateIdentifier(ComponentPrefix, (this.suppressRootDirectory) ? directoryRef.Id : directory.Id, file.Id); } Wix.Fragment fragment = new Wix.Fragment(); fragment.AddChild(directoryRef); return new Wix.Fragment[] { fragment }; }