/// <summary> /// Removes rows from the Registry table that are generated by this extension. /// </summary> /// <param name="tables">The collection of tables.</param> private void FinalizeRegistryTable(TableCollection tables) { Table registryTable = tables["Registry"]; if (null != registryTable) { foreach (Row registryRow in registryTable.Rows) { // Check if the compiler writes this registry value; if so, it should be removed. if (this.registryValues.Contains(registryRow)) { Wix.ISchemaElement elem = this.Core.GetIndexedElement(registryRow); // If the registry row was found, remove it from its parent. if (null != elem && null != elem.ParentElement) { Wix.IParentElement elemParent = elem.ParentElement as Wix.IParentElement; if (null != elemParent) { elemParent.RemoveChild(elem); } } } } } }
/// <summary> /// Mutate a WiX document. /// </summary> /// <param name="wix">The Wix document element.</param> public override void Mutate(Wix.Wix wix) { this.components.Clear(); this.directoryPaths.Clear(); this.webAddresses.Clear(); this.webDirs.Clear(); this.webDirProperties.Clear(); this.webFilters.Clear(); this.webSites.Clear(); this.webVirtualDirs.Clear(); this.rootElement = null; this.IndexElement(wix); this.MutateWebAddresses(); this.MutateWebDirs(); this.MutateWebDirProperties(); this.MutateWebSites(); this.MutateWebVirtualDirs(); // this must come after the web virtual dirs in case they harvest a directory containing a web filter file this.MutateWebFilters(); // this must come after the web site identifiers are created this.MutateComponents(); }
/// <summary> /// Removes properties defined by this extension. /// </summary> /// <param name="tables">The collection of tables.</param> private void FinalizeProperties() { string[] properties = new string[] { "DISABLEDEPENDENCYCHECK", "IGNOREDEPENDENCIES" }; foreach (string property in properties) { Wix.Property elem = this.Core.GetIndexedElement("Property", property) as Wix.Property; if (null != elem) { // If a value is defined, log a warning we're removing it. if (!String.IsNullOrEmpty(elem.Value)) { this.Core.OnMessage(DependencyWarnings.PropertyRemoved(elem.Id)); } // If the property row was found, remove it from its parent. if (null != elem.ParentElement) { Wix.IParentElement elemParent = elem.ParentElement as Wix.IParentElement; if (null != elemParent) { elemParent.RemoveChild(elem); } } } } }
/// <summary> /// Calls self-reg harvester. /// </summary> /// <param name="parentElement">The parent element.</param> /// <param name="fileSource">The file source.</param> private void HarvestSelfReg(Wix.IParentElement parentElement, string fileSource) { // try the self-reg harvester try { DllHarvester dllHarvester = new DllHarvester(); this.Core.OnMessage(UtilVerboses.HarvestingSelfReg(fileSource)); Wix.RegistryValue[] registryValues = dllHarvester.HarvestRegistryValues(fileSource); foreach (Wix.RegistryValue registryValue in registryValues) { parentElement.AddChild(registryValue); } } catch (TargetInvocationException tie) { if (tie.InnerException is EntryPointNotFoundException) { // No DllRegisterServer(), which is fine by me. } else { this.Core.OnMessage(UtilWarnings.SelfRegHarvestFailed(fileSource, tie.Message)); } } catch (Exception ex) { this.Core.OnMessage(UtilWarnings.SelfRegHarvestFailed(fileSource, ex.Message)); } }
/// <summary> /// Index an element. /// </summary> /// <param name="element">The element to index.</param> private void IndexElement(Wix.ISchemaElement element) { if (element is IIs.WebAddress) { this.webAddresses.Add(element); } else if (element is IIs.WebDir) { this.webDirs.Add(element); } else if (element is IIs.WebDirProperties) { this.webDirProperties.Add(element); } else if (element is IIs.WebFilter) { this.webFilters.Add(element); } else if (element is IIs.WebSite) { this.webSites.Add(element); } else if (element is IIs.WebVirtualDir) { this.webVirtualDirs.Add(element); } else if (element is Wix.Component) { this.components.Add(element); } else if (element is Wix.Directory) { Wix.Directory directory = (Wix.Directory)element; if (null != directory.FileSource) { this.directoryPaths.Add(directory.FileSource, directory); } } else if (element is Wix.Fragment || element is Wix.Module || element is Wix.PatchCreation || element is Wix.Product) { this.rootElement = (Wix.IParentElement)element; } // index the child elements if (element is Wix.IParentElement) { foreach (Wix.ISchemaElement childElement in ((Wix.IParentElement)element).Children) { this.IndexElement(childElement); } } }
/// <summary> /// Mutate a file. /// </summary> /// <param name="parentElement">The parent of the element to mutate.</param> /// <param name="file">The file to mutate.</param> protected void MutateFile(Wix.IParentElement parentElement, Wix.File file) { if (null == file.Source) { return; } string fileExtension = Path.GetExtension(file.Source); string fileSource = this.Core.ResolveFilePath(file.Source); if (String.Equals(".dll", fileExtension, StringComparison.OrdinalIgnoreCase) || String.Equals(".ocx", fileExtension, StringComparison.OrdinalIgnoreCase)) // ActiveX { mutateDllComServer(parentElement, fileSource); } else if (String.Equals(".exe", fileExtension, StringComparison.OrdinalIgnoreCase)) { mutateExeComServer(parentElement, fileSource); } else if (string.Equals(".plb", fileExtension, StringComparison.OrdinalIgnoreCase) || string.Equals(".tlb", fileExtension, StringComparison.OrdinalIgnoreCase)) { // try the type library harvester try { ATLTypeLibraryHarvester atlTypeLibHarvester = new ATLTypeLibraryHarvester(); this.Core.OnMessage(UtilVerboses.HarvestingTypeLib(fileSource)); Wix.RegistryValue[] registryValues = atlTypeLibHarvester.HarvestRegistryValues(fileSource); foreach (Wix.RegistryValue registryValue in registryValues) { parentElement.AddChild(registryValue); } } catch (COMException ce) { // 0x8002801C (TYPE_E_REGISTRYACCESS) // If we don't have permission to harvest typelibs, it's likely because we're on // Vista or higher and aren't an Admin, or don't have the appropriate QFE installed. if (!this.calledPerUserTLibReg && (0x8002801c == unchecked ((uint)ce.ErrorCode))) { this.Core.OnMessage(WixWarnings.InsufficientPermissionHarvestTypeLib()); } else if (0x80029C4A == unchecked ((uint)ce.ErrorCode)) // generic can't load type library { this.Core.OnMessage(UtilWarnings.TypeLibLoadFailed(fileSource, ce.Message)); } } } }
/// <summary> /// Index an element. /// </summary> /// <param name="element">The element to index.</param> private void IndexElement(Wix.ISchemaElement element) { if (element is Wix.Component) { this.components.Add(element); } else if (element is Wix.ComponentGroup) { this.componentGroups.Add(element); } else if (element is Wix.Directory) { this.directories.Add(element); } else if (element is Wix.DirectoryRef) { this.directoryRefs.Add(element); } else if (element is Wix.Feature) { this.features.Add(element); } else if (element is Wix.File) { this.files.Add(element); } else if (element is Wix.Module || element is Wix.PatchCreation || element is Wix.Product) { Debug.Assert(null == this.rootElement); this.rootElement = (Wix.IParentElement)element; } // index the child elements if (element is Wix.IParentElement) { foreach (Wix.ISchemaElement childElement in ((Wix.IParentElement)element).Children) { this.IndexElement(childElement); } } }
/// <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> /// Mutate an element. /// </summary> /// <param name="parentElement">The parent of the element to mutate.</param> /// <param name="element">The element to mutate.</param> protected void MutateElement(Wix.IParentElement parentElement, Wix.ISchemaElement element) { if (element is Wix.File) { this.MutateFile(parentElement, (Wix.File)element); } // mutate the child elements if (element is Wix.IParentElement) { 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) { this.MutateElement((Wix.IParentElement)element, childElement); } } }
private void mutateExeComServer(Wix.IParentElement parentElement, string fileSource) { try { ATLExeHarvester exeHarvester = new ATLExeHarvester(useDash); this.Core.OnMessage(UtilVerboses.HarvestingSelfReg(fileSource)); Wix.RegistryValue[] registryValues = exeHarvester.HarvestRegistryValues(fileSource); // Set Win64 on parent component if 64-bit PE. Wix.Component component = parentElement as Wix.Component; if ((component != null) && exeHarvester.Win64) { component.Win64 = Wix.YesNoType.yes; } foreach (Wix.RegistryValue registryValue in registryValues) { if ((Wix.RegistryValue.ActionType.write == registryValue.Action) && (Wix.RegistryRootType.HKCR == registryValue.Root) && string.Equals(registryValue.Key, ATLRegistryHarvester.ATLRegistrarKey)) { continue; // ignore ATL Registrar values } else if (addShellExtensionKey && (Wix.RegistryValue.ActionType.write == registryValue.Action) && (Wix.RegistryRootType.HKLM == registryValue.Root) && string.Equals(registryValue.Key, ATLRegistryHarvester.ShellKey, StringComparison.InvariantCultureIgnoreCase) && string.IsNullOrEmpty(registryValue.Name)) { continue; // ignore Shell Extension base key } else if ((Wix.RegistryValue.ActionType.write == registryValue.Action) && (Wix.RegistryRootType.HKCR == registryValue.Root) && registryValue.Key.StartsWith(@"CLSID\{") && registryValue.Key.EndsWith(@"}\LocalServer32", StringComparison.OrdinalIgnoreCase)) { // Fix double (or double-double) quotes around LocalServer32 value, if present. if (registryValue.Value.StartsWith("\"") && registryValue.Value.EndsWith("\"")) { registryValue.Value = registryValue.Value.Substring(1, registryValue.Value.Length - 2); } else if (registryValue.Value.StartsWith("\"\"") && registryValue.Value.EndsWith("\"\"")) { registryValue.Value = registryValue.Value.Substring(2, registryValue.Value.Length - 4); } parentElement.AddChild(registryValue); } else if ((Wix.RegistryValue.ActionType.write == registryValue.Action) && (Wix.RegistryRootType.HKCR == registryValue.Root) && string.Equals(registryValue.Key, "Interface", StringComparison.OrdinalIgnoreCase)) { continue; // ignore extra HKCR\Interface key } else if ((Wix.RegistryValue.ActionType.write == registryValue.Action) && (Wix.RegistryRootType.HKLM == registryValue.Root) && !registryValue.Key.StartsWith(@"SOFTWARE\Classes\Root", StringComparison.InvariantCultureIgnoreCase)) { continue; // ignore anything written to HKLM for now, unless it's under SW\Classes\Root .. } else { parentElement.AddChild(registryValue); } } } catch (Exception ex) { this.Core.OnMessage(UtilWarnings.SelfRegHarvestFailed(fileSource, ex.Message)); } }
/// <summary> /// Mutate a Wix element. /// </summary> /// <param name="wix">The Wix element to mutate.</param> private void MutateWix(Wix.Wix wix) { if (TemplateType.Fragment != this.templateType) { if (null != this.rootElement || 0 != this.features.Count) { throw new Exception("The template option cannot be used with Feature, Product, or Module elements present."); } // create a package element although it won't always be used Wix.Package package = new Wix.Package(); if (TemplateType.Module == this.templateType) { package.Id = this.GetGuid(); } package.Compressed = Wix.YesNoType.yes; package.InstallerVersion = 200; // create the root directory Wix.Directory targetDir = new Wix.Directory(); targetDir.Id = "TARGETDIR"; targetDir.Name = "SourceDir"; // add all previous root directories to the root directory foreach (Wix.Directory directory in this.directories) { if (!(directory.ParentElement is Wix.Directory || directory.ParentElement is Wix.DirectoryRef)) { ((Wix.IParentElement)directory.ParentElement).RemoveChild(directory); targetDir.AddChild(directory); } } // add children of DirectoryRef/@Id="TARGETROOT" elements to the root directory foreach (Wix.DirectoryRef directoryRef in this.directoryRefs) { if ("TARGETDIR" == directoryRef.Id) { foreach (Wix.ISchemaElement element in directoryRef.Children) { targetDir.AddChild(element); } ((Wix.IParentElement)directoryRef.ParentElement).RemoveChild(directoryRef); } } this.directories.Add(targetDir); if (TemplateType.Module == this.templateType) { Wix.Module module = new Wix.Module(); module.Id = "PUT-MODULE-NAME-HERE"; module.Language = "1033"; module.Version = "1.0.0.0"; package.Manufacturer = "PUT-COMPANY-NAME-HERE"; module.AddChild(package); // add the authoring from the fragments directly into the module foreach (Wix.Fragment fragment in wix.Children) { foreach (Wix.ISchemaElement element in fragment.Children) { module.AddChild(element); } } foreach (Wix.Fragment fragment in wix.Children) { wix.RemoveChild(fragment); } module.AddChild(targetDir); wix.AddChild(module); this.rootElement = module; } else // product { Wix.Product product = new Wix.Product(); product.Id = this.GetGuid(); product.Language = "1033"; product.Manufacturer = "PUT-COMPANY-NAME-HERE"; product.Name = "PUT-PRODUCT-NAME-HERE"; product.UpgradeCode = this.GetGuid(); product.Version = "1.0.0.0"; product.AddChild(package); Wix.Media media = new Wix.Media(); media.Id = 1; media.Cabinet = "product.cab"; media.EmbedCab = Wix.YesNoType.yes; product.AddChild(media); Wix.Feature feature = new Wix.Feature(); feature.Id = "ProductFeature"; feature.Title = "PUT-FEATURE-TITLE-HERE"; feature.Level = 1; product.AddChild(feature); this.features.Add(feature); // add the authoring from the fragments directly into the product foreach (Wix.Fragment fragment in wix.Children) { foreach (Wix.ISchemaElement element in fragment.Children) { product.AddChild(element); } } foreach (Wix.Fragment fragment in wix.Children) { wix.RemoveChild(fragment); } product.AddChild(targetDir); wix.AddChild(product); this.rootElement = product; } } }
/// <summary> /// Mutate a WiX document. /// </summary> /// <param name="wix">The Wix document element.</param> public override void Mutate(Wix.Wix wix) { this.components.Clear(); this.directories.Clear(); this.directoryRefs.Clear(); this.features.Clear(); this.files.Clear(); this.fragments.Clear(); this.rootElement = null; // index elements in this wix document this.IndexElement(wix); this.MutateWix(wix); this.MutateFiles(); this.MutateDirectories(); this.MutateComponents(); // add the components to the product feature after all the identifiers have been set if (TemplateType.Product == this.templateType) { Wix.Feature feature = (Wix.Feature) this.features[0]; foreach (Wix.Component component in this.components) { if (null != component.Id) { Wix.ComponentRef componentRef = new Wix.ComponentRef(); componentRef.Id = component.Id; feature.AddChild(componentRef); } } } // create a ComponentGroup with all the components else if (TemplateType.Fragment == this.templateType && !this.createFragments) { Wix.ComponentGroup componentGroup = new Wix.ComponentGroup(); componentGroup.Id = "ComponentGroup1"; foreach (Wix.Component component in this.components) { if (null != component.Id) { Wix.ComponentRef componentRef = new Wix.ComponentRef(); componentRef.Id = component.Id; componentGroup.AddChild(componentRef); } } Wix.Fragment fragment = new Wix.Fragment(); this.fragments.Add("ComponentGroup:1", fragment); fragment.AddChild(componentGroup); } foreach (Wix.Fragment fragment in this.fragments.Values) { wix.AddChild(fragment); } }
/// <summary> /// Mutate a Wix element. /// </summary> /// <param name="wix">The Wix element to mutate.</param> private void MutateWix(Wix.Wix wix) { if (TemplateType.Fragment != this.templateType) { if (null != this.rootElement || 0 != this.features.Count) { throw new Exception("The template option cannot be used with Feature, Product, or Module elements present."); } // create a package element although it won't always be used Wix.Package package = new Wix.Package(); if (TemplateType.Module == this.templateType) { package.Id = this.GetGuid(); } else { package.Compressed = Wix.YesNoType.yes; } package.InstallerVersion = 200; Wix.Directory targetDir = new Wix.Directory(); targetDir.Id = "TARGETDIR"; targetDir.Name = "SourceDir"; foreach (Wix.DirectoryRef directoryRef in this.directoryRefs) { if (String.Equals(directoryRef.Id, "TARGETDIR", StringComparison.OrdinalIgnoreCase)) { Wix.IParentElement parent = directoryRef.ParentElement as Wix.IParentElement; foreach (Wix.ISchemaElement element in directoryRef.Children) { targetDir.AddChild(element); } parent.RemoveChild(directoryRef); if (null != ((Wix.ISchemaElement)parent).ParentElement) { int i = 0; foreach (Wix.ISchemaElement element in parent.Children) { i++; } if (0 == i) { Wix.IParentElement supParent = (Wix.IParentElement)((Wix.ISchemaElement)parent).ParentElement; supParent.RemoveChild((Wix.ISchemaElement)parent); } } break; } } if (TemplateType.Module == this.templateType) { Wix.Module module = new Wix.Module(); module.Id = "PUT-MODULE-NAME-HERE"; module.Language = "1033"; module.Version = "1.0.0.0"; package.Manufacturer = "PUT-COMPANY-NAME-HERE"; module.AddChild(package); module.AddChild(targetDir); wix.AddChild(module); this.rootElement = module; } else // product { Wix.Product product = new Wix.Product(); product.Id = this.GetGuid(); product.Language = "1033"; product.Manufacturer = "PUT-COMPANY-NAME-HERE"; product.Name = "PUT-PRODUCT-NAME-HERE"; product.UpgradeCode = this.GetGuid(); product.Version = "1.0.0.0"; product.AddChild(package); product.AddChild(targetDir); Wix.Media media = new Wix.Media(); media.Id = "1"; media.Cabinet = "product.cab"; media.EmbedCab = Wix.YesNoType.yes; product.AddChild(media); Wix.Feature feature = new Wix.Feature(); feature.Id = "ProductFeature"; feature.Title = "PUT-FEATURE-TITLE-HERE"; feature.Level = 1; product.AddChild(feature); this.features.Add(feature); wix.AddChild(product); this.rootElement = product; } } }
/// <summary> /// Mutate a WiX document. /// </summary> /// <param name="wix">The Wix document element.</param> public override void Mutate(Wix.Wix wix) { this.components.Clear(); this.directories.Clear(); this.directoryRefs.Clear(); this.features.Clear(); this.files.Clear(); this.fragments.Clear(); this.rootElement = null; // index elements in this wix document this.IndexElement(wix); this.MutateWix(wix); this.MutateFiles(); this.MutateDirectories(); this.MutateComponents(); if (null != this.componentGroupName) { this.CreateComponentGroup(wix); } // add the components to the product feature after all the identifiers have been set if (TemplateType.Product == this.templateType) { Wix.Feature feature = (Wix.Feature)this.features[0]; foreach (Wix.ComponentGroup group in this.componentGroups) { Wix.ComponentGroupRef componentGroupRef = new Wix.ComponentGroupRef(); componentGroupRef.Id = group.Id; feature.AddChild(componentGroupRef); } } else if (TemplateType.Module == this.templateType) { foreach (Wix.ISchemaElement element in wix.Children) { if (element is Wix.Module) { foreach (Wix.ComponentGroup group in this.componentGroups) { Wix.ComponentGroupRef componentGroupRef = new Wix.ComponentGroupRef(); componentGroupRef.Id = group.Id; ((Wix.IParentElement)element).AddChild(componentGroupRef); } break; } } } //if(!this.createFragments && TemplateType.Product foreach (Wix.Fragment fragment in this.fragments.Values) { wix.AddChild(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 void MutateFile(Wix.IParentElement parentElement, Wix.File file) { if (null != file.Source) { string fileExtension = Path.GetExtension(file.Source); if (0 == String.Compare(".ax", fileExtension, true) || // DirectShow filter 0 == String.Compare(".dll", fileExtension, true) || 0 == String.Compare(".exe", fileExtension, true) || 0 == String.Compare(".ocx", fileExtension, true) || // ActiveX 0 == String.Compare(".olb", fileExtension, true) || // type library 0 == String.Compare(".tlb", fileExtension, true)) // type library { // try the assembly harvester try { AssemblyHarvester assemblyHarvester = new AssemblyHarvester(); Wix.RegistryValue[] registryValues = assemblyHarvester.HarvestRegistryValues(file.Source); foreach (Wix.RegistryValue registryValue in registryValues) { parentElement.AddChild(registryValue); } } catch { // try the self-reg harvester try { DllHarvester dllHarvester = new DllHarvester(); Wix.RegistryValue[] registryValues = dllHarvester.HarvestRegistryValues(file.Source); foreach (Wix.RegistryValue registryValue in registryValues) { parentElement.AddChild(registryValue); } } catch { // try the type library harvester try { TypeLibraryHarvester typeLibHarvester = new TypeLibraryHarvester(); Wix.RegistryValue[] registryValues = typeLibHarvester.HarvestRegistryValues(file.Source); foreach (Wix.RegistryValue registryValue in registryValues) { parentElement.AddChild(registryValue); } } catch { // ignore all exceptions } } } } } }
/// <summary> /// Finalize the SecureObjects table. /// </summary> /// <param name="tables">The collection of all tables.</param> /// <remarks> /// Nests the PermissionEx elements below their parent elements. There are no declared foreign /// keys for the parents of the SecureObjects table. /// </remarks> private void FinalizeSecureObjectsTable(TableCollection tables) { Table createFolderTable = tables["CreateFolder"]; Table secureObjectsTable = tables["SecureObjects"]; Hashtable createFolders = new Hashtable(); // index the CreateFolder table because the foreign key to this table from the // LockPermissions table is only part of the primary key of this table if (null != createFolderTable) { foreach (Row row in createFolderTable.Rows) { Wix.CreateFolder createFolder = (Wix.CreateFolder) this.Core.GetIndexedElement(row); string directoryId = (string)row[0]; if (!createFolders.Contains(directoryId)) { createFolders.Add(directoryId, new ArrayList()); } ((ArrayList)createFolders[directoryId]).Add(createFolder); } } if (null != secureObjectsTable) { foreach (Row row in secureObjectsTable.Rows) { string id = (string)row[0]; string table = (string)row[1]; Util.PermissionEx permissionEx = (Util.PermissionEx) this.Core.GetIndexedElement(row); if ("CreateFolder" == table) { ArrayList createFolderElements = (ArrayList)createFolders[id]; if (null != createFolderElements) { foreach (Wix.CreateFolder createFolder in createFolderElements) { createFolder.AddChild(permissionEx); } } else { this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, "SecureObjects", row.GetPrimaryKey(DecompilerCore.PrimaryKeyDelimiter), "LockObject", id, table)); } } else { Wix.IParentElement parentElement = (Wix.IParentElement) this.Core.GetIndexedElement(table, id); if (null != parentElement) { parentElement.AddChild(permissionEx); } else { this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, "SecureObjects", row.GetPrimaryKey(DecompilerCore.PrimaryKeyDelimiter), "LockObject", id, table)); } } } } }
/// <summary> /// Mutate a file. /// </summary> /// <param name="parentElement">The parent of the element to mutate.</param> /// <param name="file">The file to mutate.</param> protected void MutateFile(Wix.IParentElement parentElement, Wix.File file) { if (null != file.Source) { string fileExtension = Path.GetExtension(file.Source); string fileSource = this.Core.ResolveFilePath(file.Source); if (String.Equals(".dll", fileExtension, StringComparison.OrdinalIgnoreCase) || String.Equals(".ocx", fileExtension, StringComparison.OrdinalIgnoreCase)) // ActiveX { try { ATLDllHarvester dllHarvester = new ATLDllHarvester(); this.Core.OnMessage(UtilVerboses.HarvestingSelfReg(fileSource)); Wix.RegistryValue[] registryValues = dllHarvester.HarvestRegistryValues(fileSource, addShellExtensionKey); // Set Win64 on parent component if 64-bit PE. Wix.Component component = parentElement as Wix.Component; if ((component != null) && dllHarvester.Win64) { component.Win64 = Wix.YesNoType.yes; } foreach (Wix.RegistryValue registryValue in registryValues) { if ((Wix.RegistryValue.ActionType.write == registryValue.Action) && (Wix.RegistryRootType.HKCR == registryValue.Root) && string.Equals(registryValue.Key, ATLRegistryHarvester.ATLRegistrarKey, StringComparison.InvariantCultureIgnoreCase)) { continue; // ignore ATL Registrar values } else if (addShellExtensionKey && (Wix.RegistryValue.ActionType.write == registryValue.Action) && (Wix.RegistryRootType.HKLM == registryValue.Root) && string.Equals(registryValue.Key, ATLRegistryHarvester.ShellKey, StringComparison.InvariantCultureIgnoreCase) && string.IsNullOrEmpty(registryValue.Name)) { continue; // ignore Shell Extension base key } else { parentElement.AddChild(registryValue); } } } catch (TargetInvocationException tie) { if (tie.InnerException is EntryPointNotFoundException) { // No DllRegisterServer() } else { this.Core.OnMessage(UtilWarnings.SelfRegHarvestFailed(fileSource, tie.Message)); } } catch (COMException ce) { // 0x8002801C (TYPE_E_REGISTRYACCESS) // If we don't have permission to harvest typelibs, it's likely because we're on // Vista or higher and aren't an Admin, or don't have the appropriate QFE installed. if (!this.calledPerUserTLibReg && (0x8002801c == unchecked ((uint)ce.ErrorCode))) { this.Core.OnMessage(WixWarnings.InsufficientPermissionHarvestTypeLib()); } else { this.Core.OnMessage(UtilWarnings.SelfRegHarvestFailed(fileSource, ce.Message)); } } catch (Exception ex) { this.Core.OnMessage(UtilWarnings.SelfRegHarvestFailed(fileSource, ex.Message)); } } else if (String.Equals(".exe", fileExtension, StringComparison.OrdinalIgnoreCase)) { try { ATLExeHarvester exeHarvester = new ATLExeHarvester(useDash); this.Core.OnMessage(UtilVerboses.HarvestingSelfReg(fileSource)); Wix.RegistryValue[] registryValues = exeHarvester.HarvestRegistryValues(fileSource); // Set Win64 on parent component if 64-bit PE. Wix.Component component = parentElement as Wix.Component; if ((component != null) && exeHarvester.Win64) { component.Win64 = Wix.YesNoType.yes; } foreach (Wix.RegistryValue registryValue in registryValues) { if ((Wix.RegistryValue.ActionType.write == registryValue.Action) && (Wix.RegistryRootType.HKCR == registryValue.Root) && string.Equals(registryValue.Key, ATLRegistryHarvester.ATLRegistrarKey)) { continue; // ignore ATL Registrar values } else if (addShellExtensionKey && (Wix.RegistryValue.ActionType.write == registryValue.Action) && (Wix.RegistryRootType.HKLM == registryValue.Root) && string.Equals(registryValue.Key, ATLRegistryHarvester.ShellKey, StringComparison.InvariantCultureIgnoreCase) && string.IsNullOrEmpty(registryValue.Name)) { continue; // ignore Shell Extension base key } else if ((Wix.RegistryValue.ActionType.write == registryValue.Action) && (Wix.RegistryRootType.HKCR == registryValue.Root) && registryValue.Key.StartsWith(@"CLSID\{") && registryValue.Key.EndsWith(@"}\LocalServer32", StringComparison.OrdinalIgnoreCase)) { // Fix double (or double-double) quotes around LocalServer32 value, if present. if (registryValue.Value.StartsWith("\"") && registryValue.Value.EndsWith("\"")) { registryValue.Value = registryValue.Value.Substring(1, registryValue.Value.Length - 2); } else if (registryValue.Value.StartsWith("\"\"") && registryValue.Value.EndsWith("\"\"")) { registryValue.Value = registryValue.Value.Substring(2, registryValue.Value.Length - 4); } parentElement.AddChild(registryValue); } else if ((Wix.RegistryValue.ActionType.write == registryValue.Action) && (Wix.RegistryRootType.HKCR == registryValue.Root) && string.Equals(registryValue.Key, "Interface", StringComparison.OrdinalIgnoreCase)) { continue; // ignore extra HKCR\Interface key } else if ((Wix.RegistryValue.ActionType.write == registryValue.Action) && (Wix.RegistryRootType.HKLM == registryValue.Root) && !registryValue.Key.StartsWith(@"SOFTWARE\Classes\Root", StringComparison.InvariantCultureIgnoreCase)) { continue; // ignore anything written to HKLM for now, unless it's under SW\Classes\Root .. } else { parentElement.AddChild(registryValue); } } } catch (Exception ex) { this.Core.OnMessage(UtilWarnings.SelfRegHarvestFailed(fileSource, ex.Message)); } } } }
/// <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 void MutateFile(Wix.IParentElement parentElement, Wix.File file) { if (null != file.Source) { string fileExtension = Path.GetExtension(file.Source); string fileSource = this.Core.ResolveFilePath(file.Source); if (String.Equals(".ax", fileExtension, StringComparison.OrdinalIgnoreCase) || // DirectShow filter String.Equals(".dll", fileExtension, StringComparison.OrdinalIgnoreCase) || String.Equals(".exe", fileExtension, StringComparison.OrdinalIgnoreCase) || String.Equals(".ocx", fileExtension, StringComparison.OrdinalIgnoreCase)) // ActiveX { // try the assembly harvester try { AssemblyHarvester assemblyHarvester = new AssemblyHarvester(); this.Core.OnMessage(UtilVerboses.HarvestingAssembly(fileSource)); Wix.RegistryValue[] registryValues = assemblyHarvester.HarvestRegistryValues(fileSource); foreach (Wix.RegistryValue registryValue in registryValues) { parentElement.AddChild(registryValue); } // also try self-reg since we could have a mixed-mode assembly this.HarvestSelfReg(parentElement, fileSource); } catch (BadImageFormatException) // not an assembly, try raw DLL. { this.HarvestSelfReg(parentElement, fileSource); } catch (Exception ex) { this.Core.OnMessage(UtilWarnings.AssemblyHarvestFailed(fileSource, ex.Message)); } } else if (String.Equals(".olb", fileExtension, StringComparison.OrdinalIgnoreCase) || // type library String.Equals(".tlb", fileExtension, StringComparison.OrdinalIgnoreCase)) // type library { // try the type library harvester try { TypeLibraryHarvester typeLibHarvester = new TypeLibraryHarvester(); this.Core.OnMessage(UtilVerboses.HarvestingTypeLib(fileSource)); Wix.RegistryValue[] registryValues = typeLibHarvester.HarvestRegistryValues(fileSource); foreach (Wix.RegistryValue registryValue in registryValues) { parentElement.AddChild(registryValue); } } catch (COMException ce) { // 0x8002801C (TYPE_E_REGISTRYACCESS) // If we don't have permission to harvest typelibs, it's likely because we're on // Vista or higher and aren't an Admin, or don't have the appropriate QFE installed. if (!this.calledPerUserTLibReg && (0x8002801c == unchecked ((uint)ce.ErrorCode))) { this.Core.OnMessage(WixWarnings.InsufficientPermissionHarvestTypeLib()); } else if (0x80029C4A == unchecked ((uint)ce.ErrorCode)) // generic can't load type library { this.Core.OnMessage(UtilWarnings.TypeLibLoadFailed(fileSource, ce.Message)); } } } } }
/// <summary> /// Mutate a WiX document. /// </summary> /// <param name="wix">The Wix document element.</param> public override void Mutate(Wix.Wix wix) { this.components.Clear(); this.directories.Clear(); this.directoryRefs.Clear(); this.features.Clear(); this.files.Clear(); this.fragments.Clear(); this.rootElement = null; // index elements in this wix document this.IndexElement(wix); this.MutateWix(wix); this.MutateFiles(); this.MutateDirectories(); this.MutateComponents(); if (null != this.componentGroupName) { this.CreateComponentGroup(wix); } // add the components to the product feature after all the identifiers have been set if (TemplateType.Product == this.templateType) { Wix.Feature feature = (Wix.Feature) this.features[0]; foreach (Wix.ComponentGroup group in this.componentGroups) { Wix.ComponentGroupRef componentGroupRef = new Wix.ComponentGroupRef(); componentGroupRef.Id = group.Id; feature.AddChild(componentGroupRef); } } else if (TemplateType.Module == this.templateType) { foreach (Wix.ISchemaElement element in wix.Children) { if (element is Wix.Module) { foreach (Wix.ComponentGroup group in this.componentGroups) { Wix.ComponentGroupRef componentGroupRef = new Wix.ComponentGroupRef(); componentGroupRef.Id = group.Id; ((Wix.IParentElement)element).AddChild(componentGroupRef); } break; } } } //if(!this.createFragments && TemplateType.Product foreach (Wix.Fragment fragment in this.fragments.Values) { wix.AddChild(fragment); } }
private void mutateDllComServer(Wix.IParentElement parentElement, string fileSource) { try { ATLDllHarvester dllHarvester = new ATLDllHarvester(); this.Core.OnMessage(UtilVerboses.HarvestingSelfReg(fileSource)); Wix.RegistryValue[] registryValues = dllHarvester.HarvestRegistryValues(fileSource, addShellExtensionKey); // Set Win64 on parent component if 64-bit PE. Wix.Component component = parentElement as Wix.Component; if ((component != null) && dllHarvester.Win64) { component.Win64 = Wix.YesNoType.yes; } foreach (Wix.RegistryValue registryValue in registryValues) { if ((Wix.RegistryValue.ActionType.write == registryValue.Action) && (Wix.RegistryRootType.HKCR == registryValue.Root) && string.Equals(registryValue.Key, ATLRegistryHarvester.ATLRegistrarKey, StringComparison.InvariantCultureIgnoreCase)) { continue; // ignore ATL Registrar values } else if (addShellExtensionKey && (Wix.RegistryValue.ActionType.write == registryValue.Action) && (Wix.RegistryRootType.HKLM == registryValue.Root) && string.Equals(registryValue.Key, ATLRegistryHarvester.ShellKey, StringComparison.InvariantCultureIgnoreCase) && string.IsNullOrEmpty(registryValue.Name)) { continue; // ignore Shell Extension base key } else { parentElement.AddChild(registryValue); } } } catch (TargetInvocationException tie) { if (tie.InnerException is EntryPointNotFoundException) { // No DllRegisterServer() } else { this.Core.OnMessage(UtilWarnings.SelfRegHarvestFailed(fileSource, tie.Message)); } } catch (COMException ce) { // 0x8002801C (TYPE_E_REGISTRYACCESS) // If we don't have permission to harvest typelibs, it's likely because we're on // Vista or higher and aren't an Admin, or don't have the appropriate QFE installed. if (!this.calledPerUserTLibReg && (0x8002801c == unchecked ((uint)ce.ErrorCode))) { this.Core.OnMessage(WixWarnings.InsufficientPermissionHarvestTypeLib()); } else { this.Core.OnMessage(UtilWarnings.SelfRegHarvestFailed(fileSource, ce.Message)); } } catch (Exception ex) { this.Core.OnMessage(UtilWarnings.SelfRegHarvestFailed(fileSource, ex.Message)); } }
/// <summary> /// Mutate the components. /// </summary> private void MutateComponents() { foreach (Wix.Component component in this.components) { SortedList indexedElements = CollectionsUtil.CreateCaseInsensitiveSortedList(); SortedList indexedRegistryValues = CollectionsUtil.CreateCaseInsensitiveSortedList(); // index all the File elements foreach (Wix.File file in component[typeof(Wix.File)]) { indexedElements.Add(String.Concat("file/", file.Id), file); } // group all the registry values by the COM element they would correspond to and // create a COM element for each group foreach (Wix.RegistryValue registryValue in component[typeof(Wix.RegistryValue)]) { if (Wix.RegistryValue.ActionType.write == registryValue.Action && Wix.RegistryRootType.HKCR == registryValue.Root && Wix.RegistryValue.TypeType.@string == registryValue.Type) { string index = null; string[] parts = registryValue.Key.Split('\\'); // create a COM element for COM registration and index it if (1 <= parts.Length) { if (0 == String.Compare(parts[0], "AppID", true)) { // only work with GUID AppIds here if (2 <= parts.Length && parts[1].StartsWith("{") && parts[1].EndsWith("}")) { index = String.Concat(parts[0], '/', parts[1]); if (!indexedElements.Contains(index)) { Wix.AppId appId = new Wix.AppId(); appId.Id = parts[1].ToUpper(CultureInfo.InvariantCulture); indexedElements.Add(index, appId); } } } else if (0 == String.Compare(parts[0], "CLSID", true)) { if (2 <= parts.Length) { index = String.Concat(parts[0], '/', parts[1]); if (!indexedElements.Contains(index)) { Wix.Class wixClass = new Wix.Class(); wixClass.Id = parts[1].ToUpper(CultureInfo.InvariantCulture); indexedElements.Add(index, wixClass); } } } else if (0 == String.Compare(parts[0], "Component Categories", true)) { // TODO: add support for this to the compiler } else if (0 == String.Compare(parts[0], "Interface", true)) { if (2 <= parts.Length) { index = String.Concat(parts[0], '/', parts[1]); if (!indexedElements.Contains(index)) { Wix.Interface wixInterface = new Wix.Interface(); wixInterface.Id = parts[1].ToUpper(CultureInfo.InvariantCulture); indexedElements.Add(index, wixInterface); } } } else if (0 == String.Compare(parts[0], "TypeLib")) { if (3 <= parts.Length) { // use a special index to ensure progIds are processed before classes index = String.Concat(".typelib/", parts[1], '/', parts[2]); if (!indexedElements.Contains(index)) { try { // TODO: properly handle hexadecimal in version Version version = new Version(parts[2]); Wix.TypeLib typeLib = new Wix.TypeLib(); typeLib.Id = parts[1].ToUpper(CultureInfo.InvariantCulture); typeLib.MajorVersion = version.Major; typeLib.MinorVersion = version.Minor; indexedElements.Add(index, typeLib); } catch // not a valid type library registry value { index = null; } } } } else if (parts[0].StartsWith(".")) { // extension } else // ProgId (hopefully) { // use a special index to ensure progIds are processed before classes index = String.Concat(".progid/", parts[0]); if (!indexedElements.Contains(index)) { Wix.ProgId progId = new Wix.ProgId(); progId.Id = parts[0]; indexedElements.Add(index, progId); } } } // index the RegistryValue element according to the COM element it corresponds to if (null != index) { SortedList registryValues = (SortedList)indexedRegistryValues[index]; if (null == registryValues) { registryValues = CollectionsUtil.CreateCaseInsensitiveSortedList(); indexedRegistryValues.Add(index, registryValues); } registryValues.Add(String.Concat(registryValue.Key, '/', registryValue.Name), registryValue); } } } // set various values on the COM elements from their corresponding registry values Hashtable indexedProcessedRegistryValues = new Hashtable(); foreach (DictionaryEntry entry in indexedRegistryValues) { Wix.ISchemaElement element = (Wix.ISchemaElement)indexedElements[entry.Key]; string parentIndex = null; SortedList registryValues = (SortedList)entry.Value; // element-specific variables (for really tough situations) string classAppId = null; bool threadingModelSet = false; foreach (Wix.RegistryValue registryValue in registryValues.Values) { string[] parts = registryValue.Key.ToLower(CultureInfo.InvariantCulture).Split('\\'); bool processed = false; if (element is Wix.AppId) { Wix.AppId appId = (Wix.AppId)element; if (2 == parts.Length) { if (null == registryValue.Name) { appId.Description = registryValue.Value; processed = true; } } } else if (element is Wix.Class) { Wix.Class wixClass = (Wix.Class)element; if (2 == parts.Length) { if (null == registryValue.Name) { wixClass.Description = registryValue.Value; processed = true; } else if (0 == String.Compare(registryValue.Name, "AppID", true)) { classAppId = registryValue.Value; processed = true; } } else if (3 == parts.Length) { Wix.Class.ContextType contextType = Wix.Class.ContextType.None; switch (parts[2]) { case "inprochandler": if (null == registryValue.Name) { if (null == wixClass.Handler) { wixClass.Handler = "1"; processed = true; } else if ("2" == wixClass.Handler) { wixClass.Handler = "3"; processed = true; } } break; case "inprochandler32": if (null == registryValue.Name) { if (null == wixClass.Handler) { wixClass.Handler = "2"; processed = true; } else if ("1" == wixClass.Handler) { wixClass.Handler = "3"; processed = true; } } break; case "inprocserver": contextType = Wix.Class.ContextType.InprocServer; break; case "inprocserver32": contextType = Wix.Class.ContextType.InprocServer32; break; case "localserver": contextType = Wix.Class.ContextType.LocalServer; break; case "localserver32": contextType = Wix.Class.ContextType.LocalServer32; break; case "progid": if (null == registryValue.Name) { Wix.ProgId progId = (Wix.ProgId)indexedElements[String.Concat(".progid/", registryValue.Value)]; // verify that the versioned ProgId appears under this Class element // if not, toss the entire element if (null == progId || wixClass != progId.ParentElement) { element = null; } else { processed = true; } } break; case "typelib": if (null == registryValue.Name) { foreach (DictionaryEntry indexedEntry in indexedElements) { string key = (string)indexedEntry.Key; Wix.ISchemaElement possibleTypeLib = (Wix.ISchemaElement)indexedEntry.Value; if (key.StartsWith(".typelib/") && 0 == String.Compare(key, 9, registryValue.Value, 0, registryValue.Value.Length, true)) { // ensure the TypeLib is nested under the same thing we want the Class under if (null == parentIndex || indexedElements[parentIndex] == possibleTypeLib.ParentElement) { parentIndex = key; processed = true; } } } } break; case "version": if (null == registryValue.Name) { wixClass.Version = registryValue.Value; processed = true; } break; case "versionindependentprogid": if (null == registryValue.Name) { Wix.ProgId progId = (Wix.ProgId)indexedElements[String.Concat(".progid/", registryValue.Value)]; // verify that the version independent ProgId appears somewhere // under this Class element - if not, toss the entire element if (null == progId || wixClass != progId.ParentElement) { // check the parent of the parent if (null == progId || null == progId.ParentElement || wixClass != progId.ParentElement.ParentElement) { element = null; } } processed = true; } break; } if (Wix.Class.ContextType.None != contextType) { wixClass.Context |= contextType; if (null == registryValue.Name) { if ((registryValue.Value.StartsWith("[!") || registryValue.Value.StartsWith("[#")) && registryValue.Value.EndsWith("]")) { parentIndex = String.Concat("file/", registryValue.Value.Substring(2, registryValue.Value.Length - 3)); processed = true; } } else if (0 == String.Compare(registryValue.Name, "ThreadingModel", true)) { Wix.Class.ThreadingModelType threadingModel; switch (registryValue.Value.ToLower(CultureInfo.InvariantCulture)) { case "apartment": threadingModel = Wix.Class.ThreadingModelType.apartment; processed = true; break; case "both": threadingModel = Wix.Class.ThreadingModelType.both; processed = true; break; case "free": threadingModel = Wix.Class.ThreadingModelType.free; processed = true; break; case "neutral": threadingModel = Wix.Class.ThreadingModelType.neutral; processed = true; break; case "rental": threadingModel = Wix.Class.ThreadingModelType.rental; processed = true; break; case "single": threadingModel = Wix.Class.ThreadingModelType.single; processed = true; break; default: continue; } if (!threadingModelSet || wixClass.ThreadingModel == threadingModel) { wixClass.ThreadingModel = threadingModel; threadingModelSet = true; } else { element = null; break; } } } } } else if (element is Wix.Interface) { Wix.Interface wixInterface = (Wix.Interface)element; if (2 == parts.Length && null == registryValue.Name) { wixInterface.Name = registryValue.Value; processed = true; } else if (3 == parts.Length) { switch (parts[2]) { case "proxystubclsid": if (null == registryValue.Name) { wixInterface.ProxyStubClassId = registryValue.Value.ToUpper(CultureInfo.InvariantCulture); processed = true; } break; case "proxystubclsid32": if (null == registryValue.Name) { wixInterface.ProxyStubClassId32 = registryValue.Value.ToUpper(CultureInfo.InvariantCulture); processed = true; } break; case "nummethods": if (null == registryValue.Name) { wixInterface.NumMethods = Convert.ToInt32(registryValue.Value, CultureInfo.InvariantCulture); processed = true; } break; case "typelib": if (0 == String.Compare("Version", registryValue.Name, true)) { parentIndex = String.Concat(parentIndex, registryValue.Value); processed = true; } else if (null == registryValue.Name) // TypeLib guid { parentIndex = String.Concat(".typelib/", registryValue.Value, '/', parentIndex); processed = true; } break; } } } else if (element is Wix.ProgId) { Wix.ProgId progId = (Wix.ProgId)element; if (null == registryValue.Name) { if (1 == parts.Length) { progId.Description = registryValue.Value; processed = true; } else if (2 == parts.Length) { if (0 == String.Compare(parts[1], "CLSID", true)) { parentIndex = String.Concat("CLSID/", registryValue.Value); processed = true; } else if (0 == String.Compare(parts[1], "CurVer", true)) { // this registry value should usually be processed second so the // version independent ProgId should be under the versioned one parentIndex = String.Concat(".progid/", registryValue.Value); processed = true; } } } } else if (element is Wix.TypeLib) { Wix.TypeLib typeLib = (Wix.TypeLib)element; if (null == registryValue.Name) { if (3 == parts.Length) { typeLib.Description = registryValue.Value; processed = true; } else if (4 == parts.Length) { switch (parts[3].ToLower(CultureInfo.InvariantCulture)) { case "flags": int flags = Convert.ToInt32(registryValue.Value, CultureInfo.InvariantCulture); if (0x1 == (flags & 0x1)) { typeLib.Restricted = Wix.YesNoType.yes; } if (0x2 == (flags & 0x2)) { typeLib.Control = Wix.YesNoType.yes; } if (0x4 == (flags & 0x4)) { typeLib.Hidden = Wix.YesNoType.yes; } if (0x8 == (flags & 0x8)) { typeLib.HasDiskImage = Wix.YesNoType.yes; } processed = true; break; case "helpdir": if (registryValue.Value.StartsWith("[") && (registryValue.Value.EndsWith("]") || registryValue.Value.EndsWith("]\\"))) { typeLib.HelpDirectory = registryValue.Value.Substring(1, registryValue.Value.LastIndexOf(']') - 1); processed = true; } break; } } else if (5 == parts.Length && 0 == String.Compare("win32", parts[4], true)) { typeLib.Language = Convert.ToInt32(parts[3], CultureInfo.InvariantCulture); if ((registryValue.Value.StartsWith("[!") || registryValue.Value.StartsWith("[#")) && registryValue.Value.EndsWith("]")) { parentIndex = String.Concat("file/", registryValue.Value.Substring(2, registryValue.Value.Length - 3)); } processed = true; } } } // index the processed registry values by their corresponding COM element if (processed) { indexedProcessedRegistryValues.Add(registryValue, element); } } // parent the COM element if (null != element) { if (null != parentIndex) { Wix.IParentElement parentElement = (Wix.IParentElement)indexedElements[parentIndex]; if (null != parentElement) { parentElement.AddChild(element); } } else { component.AddChild(element); } // special handling for AppID since it doesn't fit the general model if (null != classAppId) { Wix.AppId appId = (Wix.AppId)indexedElements[String.Concat("AppID/", classAppId)]; // move the Class element under the AppId (and put the AppId under its old parent) if (null != appId) { // move the AppId element ((Wix.IParentElement)appId.ParentElement).RemoveChild(appId); ((Wix.IParentElement)element.ParentElement).AddChild(appId); // move the Class element ((Wix.IParentElement)element.ParentElement).RemoveChild(element); appId.AddChild(element); } } } } // remove the RegistryValue elements which were converted into COM elements // that were successfully nested under the Component element foreach (DictionaryEntry entry in indexedProcessedRegistryValues) { Wix.ISchemaElement element = (Wix.ISchemaElement)entry.Value; Wix.RegistryValue registryValue = (Wix.RegistryValue)entry.Key; while (null != element) { if (element == component) { ((Wix.IParentElement)registryValue.ParentElement).RemoveChild(registryValue); break; } element = element.ParentElement; } } } }