/// <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> /// Harvest a reg file. /// </summary> /// <param name="path">The path of the file.</param> /// <returns>A harvested registy file.</returns> public Wix.Fragment HarvestRegFile(string path) { if (null == path) { throw new ArgumentNullException("path"); } if (!File.Exists(path)) { throw new WixException(HarvesterErrors.FileNotFound(path)); } Wix.Directory directory = new Wix.Directory(); directory.Id = "TARGETDIR"; // Use absolute paths path = Path.GetFullPath(path); FileInfo file = new FileInfo(path); using (StreamReader sr = file.OpenText()) { string line; this.currentLineNumber = 0; while (null != (line = this.GetNextLine(sr))) { if (line.StartsWith(@"Windows Registry Editor Version 5.00")) { this.unicodeRegistry = true; } else if (line.StartsWith(@"REGEDIT4")) { this.unicodeRegistry = false; } else if (line.StartsWith(@"[HKEY_CLASSES_ROOT\")) { this.ConvertKey(sr, ref directory, Wix.RegistryRootType.HKCR, line.Substring(19, line.Length - 20)); } else if (line.StartsWith(@"[HKEY_CURRENT_USER\")) { this.ConvertKey(sr, ref directory, Wix.RegistryRootType.HKCU, line.Substring(19, line.Length - 20)); } else if (line.StartsWith(@"[HKEY_LOCAL_MACHINE\")) { this.ConvertKey(sr, ref directory, Wix.RegistryRootType.HKLM, line.Substring(20, line.Length - 21)); } else if (line.StartsWith(@"[HKEY_USERS\")) { this.ConvertKey(sr, ref directory, Wix.RegistryRootType.HKU, line.Substring(12, line.Length - 13)); } } } Console.WriteLine("Processing complete"); Wix.Fragment fragment = new Wix.Fragment(); fragment.AddChild(directory); return(fragment); }
/// <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 }); }
/// <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> /// 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.Package) { 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> /// Harvest a new directory or return one that was previously harvested. /// </summary> /// <param name="path">The path of the directory.</param> /// <param name="harvestChildren">The option to harvest the children of the directory.</param> /// <returns>The harvested directory.</returns> private Wix.Directory HarvestUniqueDirectory(string path, bool harvestChildren) { if (this.directoryPaths.Contains(path)) { return((Wix.Directory) this.directoryPaths[path]); } else { Wix.Directory directory = this.directoryHarvester.HarvestDirectory(path, harvestChildren); this.rootElement.AddChild(directory); // index this new directory and all of its children this.IndexElement(directory); return(directory); } }
/// <summary> /// Harvest a directory. /// </summary> /// <param name="argument">The path of the directory.</param> /// <returns>The harvested directory.</returns> public override Wix.Fragment[] Harvest(string argument) { if (null == argument) { throw new ArgumentNullException("argument"); } Wix.IParentElement harvestParent = this.HarvestDirectory(argument, true, this.GenerateType); Wix.ISchemaElement harvestElement; if (this.GenerateType == GenerateType.PayloadGroup) { Wix.PayloadGroup payloadGroup = (Wix.PayloadGroup)harvestParent; payloadGroup.Id = this.RootedDirectoryRef; harvestElement = payloadGroup; } else { Wix.Directory directory = (Wix.Directory)harvestParent; Wix.DirectoryRef directoryRef = new Wix.DirectoryRef(); directoryRef.Id = this.RootedDirectoryRef; if (this.SuppressRootDirectory) { foreach (Wix.ISchemaElement element in directory.Children) { directoryRef.AddChild(element); } } else { directoryRef.AddChild(directory); } harvestElement = directoryRef; } Wix.Fragment fragment = new Wix.Fragment(); fragment.AddChild(harvestElement); return(new Wix.Fragment[] { fragment }); }
/// <summary> /// Index an element. /// </summary> /// <param name="element">The element to index.</param> private void IndexElement(Wix.ISchemaElement element) { 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.Directory) { Wix.Directory directory = (Wix.Directory)element; if (null != directory.Id && null != directory.FileSource) { this.directoryPaths.Add(directory.FileSource, directory.Id); } } else if (element is Wix.File) { Wix.File file = (Wix.File)element; if (null != file.Id && null != file.Source) { this.filePaths[file.Source] = String.Concat("[#", file.Id, "]"); } } // index the child elements if (element is Wix.IParentElement) { foreach (Wix.ISchemaElement childElement in ((Wix.IParentElement)element).Children) { this.IndexElement(childElement); } } }
/// <summary> /// Mutate the WebFilter elements. /// </summary> private void MutateWebFilters() { IdentifierGenerator identifierGenerator = null; if (this.setUniqueIdentifiers) { identifierGenerator = new IdentifierGenerator("WebFilter", this.Core); // 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> /// 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 = this.Core.CreateIdentifierFromFilename(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 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="harvestParent">The directory for this path.</param> /// <param name="generateType"></param> /// <returns>The number of files harvested.</returns> private int HarvestDirectory(string path, string relativePath, Wix.IParentElement harvestParent, GenerateType generateType) { int fileCount = 0; Wix.Directory directory = generateType != GenerateType.PayloadGroup ? (Wix.Directory)harvestParent : null; // harvest the child directories foreach (string childDirectoryPath in Directory.GetDirectories(path)) { var childDirectoryName = Path.GetFileName(childDirectoryPath); Wix.IParentElement newParent; Wix.Directory childDirectory = null; if (generateType == GenerateType.PayloadGroup) { newParent = harvestParent; } else { childDirectory = new Wix.Directory(); newParent = childDirectory; childDirectory.Name = childDirectoryName; childDirectory.FileSource = childDirectoryPath; if (this.SetUniqueIdentifiers) { childDirectory.Id = this.Core.GenerateIdentifier(DirectoryPrefix, directory.Id, childDirectory.Name); } } int childFileCount = this.HarvestDirectory(childDirectoryPath, String.Concat(relativePath, childDirectoryName, "\\"), newParent, generateType); if (generateType != GenerateType.PayloadGroup) { // 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); string source = String.Concat(relativePath, fileName); Wix.ISchemaElement newChild; if (generateType == GenerateType.PayloadGroup) { Wix.Payload payload = new Wix.Payload(); newChild = payload; payload.SourceFile = source; } else { Wix.Component component = new Wix.Component(); newChild = component; Wix.File file = this.fileHarvester.HarvestFile(filePath); file.Source = source; 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); } harvestParent.AddChild(newChild); } } else if (generateType != GenerateType.PayloadGroup && 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 directory. /// </summary> /// <param name="path">The path of the directory.</param> /// <param name="harvestChildren">The option to harvest child directories and files.</param> /// <param name="generateType">The type to generate.</param> /// <returns>The harvested directory.</returns> private Wix.IParentElement HarvestDirectory(string path, bool harvestChildren, GenerateType generateType) { if (File.Exists(path)) { throw new WixException(ErrorMessages.ExpectedDirectoryGotFile("dir", path)); } if (null == this.RootedDirectoryRef) { this.RootedDirectoryRef = "TARGETDIR"; } // use absolute paths path = Path.GetFullPath(path); // Remove any trailing separator to ensure Path.GetFileName() will return the directory name. path = path.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); Wix.IParentElement harvestParent; if (generateType == GenerateType.PayloadGroup) { harvestParent = new Wix.PayloadGroup(); } else { Wix.Directory directory = new Wix.Directory(); directory.Name = Path.GetFileName(path); directory.FileSource = path; if (this.SetUniqueIdentifiers) { if (this.SuppressRootDirectory) { directory.Id = this.Core.GenerateIdentifier(DirectoryPrefix, this.RootedDirectoryRef); } else { directory.Id = this.Core.GenerateIdentifier(DirectoryPrefix, this.RootedDirectoryRef, directory.Name); } } harvestParent = directory; } if (harvestChildren) { try { int fileCount = this.HarvestDirectory(path, "SourceDir\\", harvestParent, generateType); if (generateType != GenerateType.PayloadGroup) { // its an error to not harvest anything with the option to keep empty directories off if (0 == fileCount && !this.KeepEmptyDirectories) { throw new WixException(HarvesterErrors.EmptyDirectory(path)); } } } catch (DirectoryNotFoundException) { throw new WixException(HarvesterErrors.DirectoryNotFound(path)); } } return(harvestParent); }
/// <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, Package, or Module elements present."); } // create a package element although it won't always be used Wix.SummaryInformation package = new Wix.SummaryInformation(); 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.Package product = new Wix.Package(); 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 the directories. /// </summary> private void MutateDirectories() { if (!this.setUniqueIdentifiers) { // assign all identifiers before fragmenting (because fragmenting requires them all to be present) IdentifierGenerator identifierGenerator = new IdentifierGenerator("Directory", this.Core); if (TemplateType.Module == this.templateType) { identifierGenerator.MaxIdentifierLength = IdentifierGenerator.MaxModuleIdentifierLength; } foreach (Wix.Directory directory in this.directories) { if (null == directory.Id) { directory.Id = identifierGenerator.GetIdentifier(directory.Name); } } } if (this.createFragments) { foreach (Wix.Directory directory in this.directories) { if (directory.ParentElement is Wix.Directory) { Wix.Directory parentDirectory = (Wix.Directory)directory.ParentElement; // parent directory must have an identifier to create a reference to it if (null == parentDirectory.Id) { return; } // create a new Fragment Wix.Fragment fragment = new Wix.Fragment(); this.fragments.Add(String.Concat("Directory:", ("TARGETDIR" == directory.Id ? null : (null != directory.Id ? directory.Id : this.fragments.Count.ToString()))), fragment); // create a new DirectoryRef Wix.DirectoryRef directoryRef = new Wix.DirectoryRef(); directoryRef.Id = parentDirectory.Id; fragment.AddChild(directoryRef); // move the Directory from the parent Directory to DirectoryRef parentDirectory.RemoveChild(directory); directoryRef.AddChild(directory); } else if (directory.ParentElement is Wix.Fragment) { // When creating fragments, remove any top-level Directory elements; // the fragments should be pulled in by their DirectoryRefs instead. Wix.Fragment parent = (Wix.Fragment)directory.ParentElement; parent.RemoveChild(directory); // Remove the fragment if it is empty. if (parent.Children.GetEnumerator().Current == null && parent.ParentElement != null) { ((Wix.IParentElement)parent.ParentElement).RemoveChild(parent); } } else if (directory.ParentElement == this.rootElement) { // create a new Fragment Wix.Fragment fragment = new Wix.Fragment(); this.fragments.Add(String.Concat("Directory:", ("TARGETDIR" == directory.Id ? null : (null != directory.Id ? directory.Id : this.fragments.Count.ToString()))), fragment); // move the Directory from the root element to the Fragment this.rootElement.RemoveChild(directory); fragment.AddChild(directory); } } } }
/// <summary> /// Mutate the components. /// </summary> private void MutateComponents() { IdentifierGenerator identifierGenerator = new IdentifierGenerator("Component", this.Core); if (TemplateType.Module == this.templateType) { identifierGenerator.MaxIdentifierLength = IdentifierGenerator.MaxModuleIdentifierLength; } foreach (Wix.Component component in this.components) { if (null == component.Id) { string firstFileId = string.Empty; // attempt to create a possible identifier from the first file identifier in the component foreach (Wix.File file in component[typeof(Wix.File)]) { firstFileId = file.Id; break; } if (string.IsNullOrEmpty(firstFileId)) { firstFileId = this.GetGuid(); } component.Id = identifierGenerator.GetIdentifier(firstFileId); } if (null == component.Guid) { if (this.AutogenerateGuids) { component.Guid = "*"; } else { component.Guid = this.GetGuid(); } } if (this.createFragments && component.ParentElement is Wix.Directory) { Wix.Directory directory = (Wix.Directory)component.ParentElement; // parent directory must have an identifier to create a reference to it if (null == directory.Id) { break; } if (this.rootElement is Wix.Module) { // add a ComponentRef for the Component Wix.ComponentRef componentRef = new Wix.ComponentRef(); componentRef.Id = component.Id; this.rootElement.AddChild(componentRef); } // create a new Fragment Wix.Fragment fragment = new Wix.Fragment(); this.fragments.Add(String.Concat("Component:", (null != component.Id ? component.Id : this.fragments.Count.ToString())), fragment); // create a new DirectoryRef Wix.DirectoryRef directoryRef = new Wix.DirectoryRef(); directoryRef.Id = directory.Id; fragment.AddChild(directoryRef); // move the Component from the the Directory to the DirectoryRef directory.RemoveChild(component); directoryRef.AddChild(component); } } }
/// <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 < this.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 = this.fragments.IndexOfKey(String.Concat("Component:", c.Id)); if (0 <= removeIndex) { this.fragments.RemoveAt(removeIndex); } } } } } else { Wix.ComponentRef componentRef = new Wix.ComponentRef(); componentRef.Id = c.Id; componentGroup.AddChild(componentRef); } } }