/// <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); }
private static void WriteWxsFile(string sOutputWxs, List <RegistryKey> wixKeys, List <RegistryValue> wixValues) { var wix = new Wix(); var wixFragment = new Fragment(); wix.AddChild(wixFragment); var wixDirectory = new Directory(); wixFragment.AddChild(wixDirectory); wixDirectory.Id = ""; var wixComponent = new Component(); wixDirectory.AddChild(wixComponent); wixComponent.Id = ""; wixComponent.Guid = "*"; foreach (RegistryKey wixKey in wixKeys) { wixComponent.AddChild(wixKey); } foreach (RegistryValue wixValue in wixValues) { wixComponent.AddChild(wixValue); } // Save to the output file using (var xw = new XmlTextWriter(new FileStream(sOutputWxs, FileMode.Create, FileAccess.Write, FileShare.Read), Encoding.UTF8)) { xw.Formatting = Formatting.Indented; wix.OutputXml(xw); } }
/// <summary> /// Mutate the directories. /// </summary> private void MutateDirectories() { foreach (Wix.Directory directory in this.directories) { string path = directory.FileSource; // create a new directory element without the FileSource attribute if (null != path) { Wix.Directory newDirectory = new Wix.Directory(); newDirectory.Id = directory.Id; newDirectory.Name = directory.Name; foreach (Wix.ISchemaElement element in directory.Children) { newDirectory.AddChild(element); } ((Wix.IParentElement)directory.ParentElement).AddChild(newDirectory); ((Wix.IParentElement)directory.ParentElement).RemoveChild(directory); if (null != newDirectory.Id) { this.directoryPaths[path.ToLower(CultureInfo.InvariantCulture)] = String.Concat("[", newDirectory.Id, "]"); } } } }
/// <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 }); }
protected Directory GetChildDirectoryByName(Directory parent, string name) { if (string.IsNullOrEmpty(name)) { return(parent); } foreach (ISchemaElement element in parent.Children) { if (element is Directory) { if (((Directory)element).Name == name) { return(element as Directory); } } } // Not found so create it. Directory directory = CreateDirectoryByParentId(parent.Id, name); parent.AddChild(directory); return(directory); }
/// <summary> /// Actions under the resolver. /// </summary> protected override void ExecuteTaskResolved() { GuidCacheXml guidcachexml = GuidCacheXml.Load(new FileInfo(Bag.GetString(AttributeName.GuidCacheFile)).OpenRead()); // Global structure of the WiX fragment file var wix = new Wix(); var wixFragmentComponents = new Fragment(); // Fragment with the payload wix.AddChild(wixFragmentComponents); var wixDirectoryRef = new DirectoryRef(); // Mount into the directories tree, defined externally wixFragmentComponents.AddChild(wixDirectoryRef); wixDirectoryRef.Id = Bag.GetString(AttributeName.WixDirectoryId); var wixDirectory = new Directory(); // A locally created nameless directory that does not add any nested folders but defines the sources location wixDirectoryRef.AddChild(wixDirectory); wixDirectory.Id = DirectoryId; wixDirectory.FileSource = Bag.GetString(AttributeName.ProductBinariesDir); var wixFragmentGroup = new Fragment(); // Fragment with the component-group that collects the components wix.AddChild(wixFragmentGroup); var wixComponentGroup = new ComponentGroup(); // ComponentGroup that collects the components wixFragmentGroup.AddChild(wixComponentGroup); wixComponentGroup.Id = Bag.GetString(AttributeName.WixComponentGroupId); // A component for the generated Registry entries var wixComponentRegistry = new Component(); wixDirectory.AddChild(wixComponentRegistry); wixComponentRegistry.Id = RegistryComponentIdPrefix; wixComponentRegistry.Guid = guidcachexml[GuidIdXml.MsiComponent_ProductBinaries_Registry_Hkmu].ToString("B").ToUpper(); wixComponentRegistry.DiskId = Bag.Get <int>(AttributeName.DiskId); wixComponentRegistry.Location = Component.LocationType.local; var wixComponentRegistryRef = new ComponentRef(); wixComponentGroup.AddChild(wixComponentRegistryRef); wixComponentRegistryRef.Id = wixComponentRegistry.Id; // Create the Registry key for the Plugins section CreatePluginsRegistryKey(wixComponentRegistry); // Load the AllAssemblies file AllAssembliesXml allassembliesxml = AllAssembliesXml.LoadFrom(Bag.Get <TaskItemByValue>(AttributeName.AllAssembliesXml).ItemSpec); // Tracks the files on the target machine, to prevent the same file from being installed both as an assembly and as a reference var mapTargetFiles = new Dictionary <string, string>(); int nGeneratedComponents = ProcessAssemblies(wixDirectory, wixComponentGroup, wixComponentRegistry, allassembliesxml, mapTargetFiles, guidcachexml); // Save to the output file using (var xw = new XmlTextWriter(new FileStream(Bag.GetString(AttributeName.OutputFile), FileMode.Create, FileAccess.Write, FileShare.Read), Encoding.UTF8)) { xw.Formatting = Formatting.Indented; wix.OutputXml(xw); } // Report (also to see the target in the build logs) Log.LogMessage(MessageImportance.Normal, "Generated {0} product binary components.", nGeneratedComponents); }
private void LoadGacAssembly(bool isWin64, Artifact artifact, string rootFolderPath, Directory rootDirectory) { // Create a new component for the gac assembly using the gac guid. string guid = artifact.GetMetadata(Constants.Catalogue.Artifact.GacGuid); if (string.IsNullOrEmpty(guid)) { guid = System.Guid.Empty.ToString(); } Component component = CreateComponent(isWin64, artifact.ProjectRelativePath, new System.Guid(guid), Wix.Xml.Id.GacPrefix); // Put the component into a special directory. Directory gacDirectory = GetDirectory(rootDirectory, "Gac"); gacDirectory.AddChild(component); // Create a file, not adding the assembly application property. File file = CreateFile(artifact.ProjectRelativePath, FilePath.GetAbsolutePath(artifact.ProjectRelativePath, rootFolderPath), Wix.Xml.Id.GacPrefix); component.AddChild(file); file.KeyPath = YesNoType.yes; file.Assembly = File.AssemblyType.net; }
/// <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> /// 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> /// Creates a new or uses the root directory to add the newly-created component with files being installed. /// </summary> private void ConvertFiles_AddToDirectory(FolderXml folderxml, Component wixComponent, DirectoryRef wixDirectoryRef) { if (folderxml.TargetRoot != TargetRootXml.InstallDir) { throw new InvalidOperationException(string.Format("Only the InstallDir target root is supported.")); } // No relative path — nothing to create if (folderxml.TargetDir.Length == 0) { wixDirectoryRef.AddChild(wixComponent); return; } // Create the folder structure, add to the innermost string[] arDirectoryChain = folderxml.TargetDir.Split('\\'); Directory wixParentDir = null; for (int a = 0; a < arDirectoryChain.Length; a++) { bool bInnermost = a == arDirectoryChain.Length - 1; // Whether this is the folder in which are the files itself // Create var wixDirectory = new Directory { Name = arDirectoryChain[a] }; // Mount self into the hierarchy if (wixParentDir != null) { wixParentDir.AddChild(wixDirectory); // Previous dir } else { wixDirectoryRef.AddChild(wixDirectory); // The very root } wixParentDir = wixDirectory; // Non-innermost folders get a suffix to their ID if (bInnermost) { wixDirectory.Id = string.Format("{0}.{1}", DirectoryIdPrefix, folderxml.Id); } else { wixDirectory.Id = string.Format("{0}.{1}.P{2}", DirectoryIdPrefix, folderxml.Id, arDirectoryChain.Length - 1 - a); } // Mount the component into the innermost dir if (bInnermost) { wixDirectory.AddChild(wixComponent); } } }
/// <summary> /// Processes the files that should be taken from the “References” folder and installed “AS IS”. /// </summary> private int ProcessReferences(Directory wixDirectory, ComponentGroup wixComponentGroup, AllAssembliesXml allassembliesxml, Dictionary <string, string> mapTargetFiles) { int nGeneratedComponents = 0; // Replaces illegal chars with underscores var regexMakeId = new Regex("[^a-zA-Z0-9_.]"); foreach (ItemGroupXml group in allassembliesxml.ItemGroup) { if (group.References == null) { continue; } foreach (ReferenceXml referencexml in group.References) { nGeneratedComponents++; var fiReference = new FileInfo(Path.Combine(Bag.GetString(AttributeName.ProductReferencesDir), referencexml.Include)); if (!fiReference.Exists) { throw new InvalidOperationException(string.Format("The reference file “{0}” could not be found.", fiReference.FullName)); } string sIdSuffix = regexMakeId.Replace(fiReference.Name, "_"); // Create the component for the assembly (one per assembly) var wixComponent = new Component(); wixDirectory.AddChild(wixComponent); wixComponent.Id = string.Format("{0}.{1}", FileComponentIdPrefix, sIdSuffix); wixComponent.Guid = referencexml.MsiGuid; wixComponent.DiskId = Bag.Get <int>(AttributeName.DiskId); wixComponent.Location = Component.LocationType.local; // Register component in the group var componentref = new ComponentRef(); wixComponentGroup.AddChild(componentref); componentref.Id = wixComponent.Id; // Add the reference file (and make it the key path) var wixFileReference = new File(); wixComponent.AddChild(wixFileReference); wixFileReference.Id = string.Format("{0}.{1}", FileIdPrefix, sIdSuffix); wixFileReference.Name = fiReference.Name; wixFileReference.KeyPath = YesNoType.yes; wixFileReference.Checksum = YesNoType.yes; wixFileReference.Vital = YesNoType.yes; wixFileReference.ReadOnly = YesNoType.yes; RegisterTargetFile(wixFileReference.Name, string.Format("The “{0}” reference.", referencexml.Include), mapTargetFiles); } } return(nGeneratedComponents); }
public void Load(bool isWin64, Artifact artifact, string rootFolderPath, Directory rootDirectory, Directory directory) { // Create a component for this artifact. string guid = artifact.GetMetadata(Constants.Catalogue.Artifact.Guid); if (string.IsNullOrEmpty(guid)) { guid = System.Guid.Empty.ToString(); } Component component = CreateComponent(isWin64, artifact.ProjectRelativePath, new System.Guid(guid)); directory.AddChild(component); // Load all details into the component. Load(isWin64, artifact, rootFolderPath, rootDirectory, directory, component); }
protected Directory GetChildDirectory(Directory parent, string id, string name) { foreach (ISchemaElement element in parent.Children) { if (element is Directory) { if (((Directory)element).Id == id) { return(element as Directory); } } } // Not found so create it. Directory directory = CreateDirectory(id, name); parent.AddChild(directory); return(directory); }
/// <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> /// 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> /// 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 }; }
private void MutateDirectories() { foreach (Wix.Directory directory in this.directories) { string path = directory.FileSource; // create a new directory element without the FileSource attribute if (null != path) { Wix.Directory newDirectory = new Wix.Directory(); newDirectory.Id = directory.Id; newDirectory.Name = directory.Name; foreach (Wix.ISchemaElement element in directory.Children) { newDirectory.AddChild(element); } ((Wix.IParentElement)directory.ParentElement).AddChild(newDirectory); ((Wix.IParentElement)directory.ParentElement).RemoveChild(directory); if (null != newDirectory.Id) { this.directoryPaths[path.ToLower(CultureInfo.InvariantCulture)] = String.Concat("[", newDirectory.Id, "]"); } } } }
/// <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> /// Processes those AllAssemblies.Xml entries that are our own product assemblies. /// </summary> private int ProcessAssemblies(Directory wixDirectory, ComponentGroup wixComponentGroup, Component wixComponentRegistry, AllAssembliesXml allassembliesxml, Dictionary <string, string> mapTargetFiles, GuidCacheXml guidcachexml) { // Collect the assemblies int nGeneratedComponents = 0; foreach (ItemGroupXml group in allassembliesxml.ItemGroup) { if (group.AllAssemblies == null) { continue; } foreach (AssemblyXml assemblyxml in group.AllAssemblies) { nGeneratedComponents++; FileInfo fiAssembly = FindAssemblyFile(assemblyxml); string sExtension = fiAssembly.Extension.TrimStart('.'); // The extension without a dot // Create the component for the assembly (one per assembly) var wixComponent = new Component(); wixDirectory.AddChild(wixComponent); wixComponent.Id = string.Format("{0}.{1}.{2}", FileComponentIdPrefix, assemblyxml.Include, sExtension); wixComponent.Guid = assemblyxml.MsiGuid; wixComponent.DiskId = Bag.Get <int>(AttributeName.DiskId); wixComponent.Location = Component.LocationType.local; // Register component in the group var componentref = new ComponentRef(); wixComponentGroup.AddChild(componentref); componentref.Id = wixComponent.Id; // Add the assembly file (and make it the key path) var wixFileAssembly = new File(); wixComponent.AddChild(wixFileAssembly); wixFileAssembly.Id = string.Format("{0}.{1}.{2}", FileIdPrefix, assemblyxml.Include, sExtension); wixFileAssembly.Name = string.Format("{0}.{1}", assemblyxml.Include, sExtension); wixFileAssembly.KeyPath = YesNoType.yes; wixFileAssembly.Checksum = YesNoType.yes; wixFileAssembly.Vital = YesNoType.yes; wixFileAssembly.ReadOnly = YesNoType.yes; RegisterTargetFile(wixFileAssembly.Name, string.Format("The {0} product assembly.", assemblyxml.Include), mapTargetFiles); // Check whether it's a managed or native assembly AssemblyName assemblyname = null; try { assemblyname = AssemblyName.GetAssemblyName(fiAssembly.FullName); } catch (BadImageFormatException) { } // Add COM Self-Registration data if (assemblyxml.ComRegister) { /* * foreach(ISchemaElement harvested in HarvestComSelfRegistration(wixFileAssembly, fiAssembly)) * wixComponent.AddChild(harvested); */ SelfRegHarvester.Harvest(fiAssembly, assemblyname != null, wixComponent, wixFileAssembly); } // Ensure the managed DLL has a strong name if ((assemblyname != null) && (Bag.Get <bool>(AttributeName.RequireStrongName))) { byte[] token = assemblyname.GetPublicKeyToken(); if ((token == null) || (token.Length == 0)) { throw new InvalidOperationException(string.Format("The assembly “{0}” does not have a strong name.", assemblyxml.Include)); } } // Add PDBs if (Bag.Get <bool>(AttributeName.IncludePdb)) { HarvestSatellite(assemblyxml, assemblyxml.Include + ".pdb", wixComponent, MissingSatelliteErrorLevel.Error, "PDB file", mapTargetFiles); } // Add XmlDocs if ((assemblyname != null) && (Bag.Get <bool>(AttributeName.IncludeXmlDoc))) { HarvestSatellite(assemblyxml, assemblyxml.Include + ".xml", wixComponent, MissingSatelliteErrorLevel.Error, "XmlDoc file", mapTargetFiles); } // Add configs HarvestSatellite(assemblyxml, assemblyxml.Include + "." + sExtension + ".config", wixComponent, (assemblyxml.HasAppConfig ? MissingSatelliteErrorLevel.Error : MissingSatelliteErrorLevel.None), "application configuration file", mapTargetFiles); HarvestSatellite(assemblyxml, assemblyxml.Include + "." + sExtension + ".manifest", wixComponent, (assemblyxml.HasMainfest ? MissingSatelliteErrorLevel.Error : MissingSatelliteErrorLevel.None), "assembly manifest file", mapTargetFiles); HarvestSatellite(assemblyxml, assemblyxml.Include + ".XmlSerializers." + sExtension, wixComponent, (assemblyxml.HasXmlSerializers ? MissingSatelliteErrorLevel.Error : MissingSatelliteErrorLevel.None), "serialization assembly", mapTargetFiles); // Add publisher policy assemblies if (assemblyname != null) { HarvestPublisherPolicyAssemblies(assemblyxml, wixDirectory, wixComponentGroup, ref nGeneratedComponents, mapTargetFiles, guidcachexml); } // Register as an OmeaPlugin if (assemblyname != null) { RegisterPlugin(assemblyxml, wixFileAssembly, wixComponentRegistry); } } } return(nGeneratedComponents); }
private void HarvestPublisherPolicyAssemblies(AssemblyXml assemblyxml, Directory directory, ComponentGroup componentgroup, ref int nGeneratedComponents, Dictionary <string, string> mapTargetFiles, GuidCacheXml guidcachexml) { if (!Bag.Get <bool>(AttributeName.IncludePublisherPolicy)) { return; } int nWasGeneratedComponents = nGeneratedComponents; var diFolder = new DirectoryInfo(Bag.GetString(AttributeName.ProductBinariesDir)); string sSatelliteWildcard = string.Format("Policy.*.{0}.{1}", assemblyxml.Include, "dll"); // Even an EXE assembly has a DLL policy file foreach (FileInfo fiPolicyAssembly in diFolder.GetFiles(sSatelliteWildcard)) { // Find the companion policy config file var fiPolicyConfig = new FileInfo(Path.ChangeExtension(fiPolicyAssembly.FullName, ".Config")); if (!fiPolicyConfig.Exists) { throw new InvalidOperationException(string.Format("Could not locate the publisher policy config file for the assembly “{0}”; expected: “{1}”.", fiPolicyAssembly.FullName, fiPolicyConfig.FullName)); } // We have to create a new component for each of the DLLs we'd like to GAC as publisher policy assemblies nGeneratedComponents++; // Create the component for the assembly (one per assembly) var component = new Component(); directory.AddChild(component); component.Id = string.Format("{0}.{1}", FileComponentIdPrefix, fiPolicyAssembly.Name); component.Guid = guidcachexml[assemblyxml.Include + " PublisherPolicy"].ToString("B").ToUpper(); component.DiskId = Bag.Get <int>(AttributeName.DiskId); component.Location = Component.LocationType.local; // Register component in the group var componentref = new ComponentRef(); componentgroup.AddChild(componentref); componentref.Id = component.Id; // Add the assembly file (and make it the key path) var fileAssembly = new File(); component.AddChild(fileAssembly); fileAssembly.Id = string.Format("{0}.{1}", FileIdPrefix, fiPolicyAssembly.Name); fileAssembly.Name = fiPolicyAssembly.Name; fileAssembly.KeyPath = YesNoType.yes; fileAssembly.Checksum = YesNoType.yes; fileAssembly.Vital = YesNoType.no; fileAssembly.Assembly = File.AssemblyType.net; fileAssembly.ReadOnly = YesNoType.yes; RegisterTargetFile(fileAssembly.Name, string.Format("Publisher policy assembly file for the {0} product assembly.", assemblyxml.Include), mapTargetFiles); // Add the policy config file var filePolicy = new File(); component.AddChild(filePolicy); filePolicy.Id = string.Format("{0}.{1}", FileIdPrefix, fiPolicyConfig.Name); filePolicy.Name = fiPolicyConfig.Name; filePolicy.KeyPath = YesNoType.no; filePolicy.Checksum = YesNoType.yes; filePolicy.Vital = YesNoType.no; filePolicy.ReadOnly = YesNoType.yes; RegisterTargetFile(fileAssembly.Name, string.Format("Publisher policy configuration file for the {0} product assembly.", assemblyxml.Include), mapTargetFiles); } if (nWasGeneratedComponents == nGeneratedComponents) // None were actually collected { throw new InvalidOperationException(string.Format("Could not locate the Publisher Policy assemblies for the “{0}” assembly. The expected full path is “{1}\\{2}”.", assemblyxml.Include, diFolder.FullName, sSatelliteWildcard)); } }
/// <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); }
private void HarvestProjectOutputGroupFile(string baseDir, string projectName, string pogName, string pogFileSource, string filePath, string fileName, string link, Wix.IParentElement parentDir, string parentDirId, Wix.Component component, Wix.File file, Dictionary<string, bool> seenList) { string varFormat = VariableFormat; if (this.generateWixVars) { varFormat = WixVariableFormat; } if (pogName.Equals("Satellites", StringComparison.OrdinalIgnoreCase)) { Wix.Directory locDirectory = new Wix.Directory(); locDirectory.Name = Path.GetFileName(Path.GetDirectoryName(Path.GetFullPath(filePath))); file.Source = String.Concat(String.Format(CultureInfo.InvariantCulture, varFormat, projectName, pogFileSource), "\\", locDirectory.Name, "\\", Path.GetFileName(filePath)); if (!seenList.ContainsKey(file.Source)) { parentDir.AddChild(locDirectory); locDirectory.AddChild(component); component.AddChild(file); seenList.Add(file.Source, true); if (this.setUniqueIdentifiers) { locDirectory.Id = this.Core.GenerateIdentifier(DirectoryPrefix, parentDirId, locDirectory.Name); file.Id = this.Core.GenerateIdentifier(FilePrefix, locDirectory.Id, fileName); component.Id = this.Core.GenerateIdentifier(ComponentPrefix, locDirectory.Id, file.Id); } else { locDirectory.Id = HarvesterCore.GetIdentifierFromName(String.Format(DirectoryIdFormat, (parentDir is Wix.DirectoryRef) ? ((Wix.DirectoryRef)parentDir).Id : parentDirId, locDirectory.Name)); file.Id = HarvesterCore.GetIdentifierFromName(String.Format(CultureInfo.InvariantCulture, VSProjectHarvester.FileIdFormat, projectName, pogName, String.Concat(locDirectory.Name, ".", fileName))); component.Id = HarvesterCore.GetIdentifierFromName(String.Format(CultureInfo.InvariantCulture, VSProjectHarvester.ComponentIdFormat, projectName, pogName, String.Concat(locDirectory.Name, ".", fileName))); } } } else { file.Source = GenerateSourceFilePath(baseDir, projectName, pogFileSource, filePath, link, varFormat); if (!seenList.ContainsKey(file.Source)) { component.AddChild(file); parentDir.AddChild(component); seenList.Add(file.Source, true); if (this.setUniqueIdentifiers) { file.Id = this.Core.GenerateIdentifier(FilePrefix, parentDirId, fileName); component.Id = this.Core.GenerateIdentifier(ComponentPrefix, parentDirId, file.Id); } else { file.Id = HarvesterCore.GetIdentifierFromName(String.Format(CultureInfo.InvariantCulture, VSProjectHarvester.FileIdFormat, projectName, pogName, fileName)); component.Id = HarvesterCore.GetIdentifierFromName(String.Format(CultureInfo.InvariantCulture, VSProjectHarvester.ComponentIdFormat, projectName, pogName, fileName)); } } } }
/// <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> /// 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> /// 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> /// 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; }