private void LoadAssembly(bool isWin64, Artifact artifact, string rootFolderPath, Directory rootDirectory, Component component) { // Create a file. File file = CreateFile(artifact.ProjectRelativePath, FilePath.GetAbsolutePath(artifact.ProjectRelativePath, rootFolderPath)); component.AddChild(file); file.KeyPath = YesNoType.yes; file.Assembly = File.AssemblyType.net; // Set the assembly application which will copy the assembly to the install location, event if it is subsequently installed into the GAC. file.AssemblyApplication = file.Id; // Check whether to register the file. if (artifact.GetBooleanMetadata(Constants.Catalogue.Artifact.Register)) { RegisterAssembly(artifact, rootFolderPath, component); } if (artifact.GetBooleanMetadata(Constants.Catalogue.Artifact.RegisterPackages)) { RegisterPackages(artifact, rootFolderPath, component); } // Check whether the assembly is to be loaded into the gac as well. if (artifact.GetBooleanMetadata(Constants.Catalogue.Artifact.InstallInGac)) { LoadGacAssembly(isWin64, artifact, rootFolderPath, rootDirectory); } }
/// <summary> /// Takes the values, searches them for the file paths and replaces them with references to the file ID. /// </summary> private static void TranslateValues(RegistryValue[] values, File wixFile, FileInfo fi) { Regex regexPath = CreateResolveFileRegex(fi); string sFileReference = string.Format("[#{0}]", wixFile.Id); foreach (RegistryValue value in values) { // Use HKMU instead of HKLM for COM registration if (value.Root == RegistryRootType.HKLM) { value.Root = RegistryRootType.HKMU; } // Use HLMU\Software\Classes instead of HKCR if (value.Root == RegistryRootType.HKCR) { value.Root = RegistryRootType.HKMU; value.Key = "Software\\Classes\\" + value.Key; } // See for the file references if (value.Name != null) { value.Name = regexPath.Replace(value.Name, sFileReference); } if (value.Value != null) { value.Value = regexPath.Replace(value.Value, sFileReference); } } }
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> /// Processes the installation files, produces the WiX data. /// </summary> private int ConvertFiles(DirectoryRef wixDirectoryRef, ComponentGroup wixComponentGroup, InstallationDataXml dataxml, IDictionary <string, string> macros) { int nProduced = 0; // Each installation folder derives a component, regardless of whether there are more files in the same folder, or not foreach (FolderXml folderxml in dataxml.Files) { folderxml.AssertValid(); // Create the component with the files var wixComponent = new Component(); wixComponent.Id = string.Format("{0}.{1}", ComponentIdPrefix, folderxml.Id); wixComponent.Guid = folderxml.MsiComponentGuid; wixComponent.DiskId = Bag.Get <int>(AttributeName.DiskId); wixComponent.Location = Component.LocationType.local; ConvertFiles_AddToDirectory(folderxml, wixComponent, wixDirectoryRef); // To the directory structure // Add to the feature var wixComponentRef = new ComponentRef(); wixComponentRef.Id = wixComponent.Id; wixComponentGroup.AddChild(wixComponentRef); // To the feature var diSource = new DirectoryInfo(Path.Combine(LocalInstallDataResolved.ResolveSourceDirRoot(folderxml.SourceRoot, Bag), folderxml.SourceDir)); if (!diSource.Exists) { throw new InvalidOperationException(string.Format("The source folder “{0}” does not exist.", diSource.FullName)); } // Add files foreach (FileXml filexml in folderxml.Files) { filexml.AssertValid(); FileInfo[] files = diSource.GetFiles(filexml.SourceName); if (files.Length == 0) { throw new InvalidOperationException(string.Format("There are no files matching the “{0}” mask in the source folder “{1}”.", filexml.SourceName, diSource.FullName)); } if ((files.Length > 1) && (filexml.TargetName.Length > 0)) { throw new InvalidOperationException(string.Format("There are {2} files matching the “{0}” mask in the source folder “{1}”, in which case it's illegal to specify a target name for the file.", filexml.SourceName, diSource.FullName, files.Length)); } foreach (FileInfo fiSource in files) { nProduced++; var wixFile = new File(); wixComponent.AddChild(wixFile); wixFile.Id = string.Format("{0}.{1}.{2}", FileIdPrefix, folderxml.Id, fiSource.Name).Replace('-', '_').Replace(' ', '_'); // Replace chars that are not allowed in the ID wixFile.Name = filexml.TargetName.Length > 0 ? filexml.TargetName : fiSource.Name; // Explicit target name, if present and if a single file; otherwise, use from source wixFile.Checksum = YesNoType.yes; wixFile.ReadOnly = YesNoType.yes; wixFile.Source = fiSource.FullName; } } } return(nProduced); }
/// <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> /// Decompile the HelpNamespace table. /// </summary> /// <param name="table">The table to decompile.</param> private void DecompileHelpNamespaceTable(Table table) { foreach (Row row in table.Rows) { VS.HelpCollection helpCollection = new VS.HelpCollection(); helpCollection.Id = (string)row[0]; helpCollection.Name = (string)row[1]; if (null != row[3]) { helpCollection.Description = (string)row[3]; } if (this.Core.RootElement is Wix.Module) { helpCollection.SuppressCustomActions = VS.YesNoType.yes; } Wix.File file = (Wix.File) this.Core.GetIndexedElement("File", (string)row[2]); if (null != file) { file.AddChild(helpCollection); } else if (0 != String.Compare(helpCollection.Id, "MS_VSIPCC_v80", StringComparison.Ordinal) && 0 != String.Compare(helpCollection.Id, "MS.VSIPCC.v90", StringComparison.Ordinal)) { this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerCore.PrimaryKeyDelimiter), "File_Collection", (string)row[2], "File")); } this.Core.IndexElement(row, helpCollection); } }
/// <summary> /// Checks whether the DLL defines an Omea plugin, and adds registration for it, if that is the case. /// </summary> private static void RegisterPlugin(AssemblyXml assemblyxml, File wixFileAssembly, Component wixComponentRegistry) { Assembly assembly = Assembly.Load(assemblyxml.Include); foreach (Type type in assembly.GetTypes()) { if (type.ContainsGenericParameters) { continue; // Generics cannot be plugins } if (type.FindInterfaces(delegate(Type m, object filterCriteria) { return((m.Name == "IPlugin") && (m.Assembly.GetName().Name == "OpenAPI")); }, null).Length == 0) { continue; // Not a single plugin in this DLL } // Yes, it's a plugin — produce registration in the Registry var wixRegValue = new RegistryValue(); wixComponentRegistry.AddChild(wixRegValue); wixRegValue.Id = string.Format("{0}.Plugin.{1}", RegistryValueIdPrefix, assemblyxml.Include); wixRegValue.Action = RegistryValue.ActionType.write; wixRegValue.Root = RegistryRootType.HKMU; wixRegValue.Key = PluginsRegistryKey; wixRegValue.Name = Regex.Replace(assemblyxml.Include, "(.+?)(Plugin)?", "$1"); wixRegValue.Type = RegistryValue.TypeType.@string; wixRegValue.Value = string.Format("[#{0}]", wixFileAssembly.Id); } }
/// <summary> /// Decompile the HelpNamespace table. /// </summary> /// <param name="table">The table to decompile.</param> private void DecompileHelpNamespaceTable(Table table) { foreach (Row row in table.Rows) { VS.HelpCollection helpCollection = new VS.HelpCollection(); helpCollection.Id = (string)row[0]; helpCollection.Name = (string)row[1]; if (null != row[3]) { helpCollection.Description = (string)row[3]; } Wix.File file = (Wix.File) this.Core.GetIndexedElement("File", (string)row[2]); if (null != file) { file.AddChild(helpCollection); } else { this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerCore.PrimaryKeyDelimiter), "File_Collection", (string)row[2], "File")); } this.Core.IndexElement(row, helpCollection); } }
/// <summary> /// Finalize the Perfmon table. /// </summary> /// <param name="tables">The collection of all tables.</param> /// <remarks> /// Since the PerfCounter element nests under a File element, but /// the Perfmon table does not have a foreign key relationship with /// the File table (instead it has a formatted string that usually /// refers to a file row - but doesn't have to), the nesting must /// be inferred during finalization. /// </remarks> private void FinalizePerfmonTable(TableCollection tables) { Table perfmonTable = tables["Perfmon"]; if (null != perfmonTable) { foreach (Row row in perfmonTable.Rows) { string formattedFile = (string)row[1]; Util.PerfCounter perfCounter = (Util.PerfCounter) this.Core.GetIndexedElement(row); // try to "de-format" the File column's value to determine the proper parent File element if ((formattedFile.StartsWith("[#") || formattedFile.StartsWith("[!")) && formattedFile.EndsWith("]")) { string fileId = formattedFile.Substring(2, formattedFile.Length - 3); Wix.File file = (Wix.File) this.Core.GetIndexedElement("File", fileId); if (null != file) { file.AddChild(perfCounter); } else { this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, perfmonTable.Name, row.GetPrimaryKey(DecompilerCore.PrimaryKeyDelimiter), "File", formattedFile, "File")); } } else { // TODO: warn about this being undecompilable because its not well-formed } } } }
/// <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> /// Gets the file object for the ApplicationEntry. /// </summary> public Wix.File GetApplicationEntryFile() { if (null != this.applicationRoot && null != this.applicationEntry.Content && null == this.applicationEntryFile) { Wix.Directory applicationDir = this.GetApplicationRootDirectory(); this.applicationEntryFile = this.GetFile(this.applicationEntry.Content, this.applicationRootDirectory); } return(this.applicationEntryFile); }
protected static File CreateFile(string projectPath, string sourcePath, string prefix) { File file = new File(); file.Id = CreateFileId(projectPath, prefix); file.Name = Path.GetFileName(projectPath); file.Compressed = Wix.Xml.CompressedDefault; file.Source = sourcePath; return(file); }
/// <summary> /// Add a scraped directory to the UI. /// </summary> /// <param name="nodes">The NodeCollection under which the new directory should be added.</param> /// <param name="rootDirectory">Root of the scraped directory info's.</param> /// <param name="directory">The scraped directory to add.</param> /// <param name="skip">true if the directory itself shouldn't be added; false otherwise.</param> private void AddDirectory(TreeNodeCollection nodes, string currentPath, Wix.Directory rootDirectory, Wix.Directory directory, bool skip) { // get the directory icon, add it to the image list, then free it immediately if (!skip) { Icon folderIcon = NativeMethods.GetDirectoryIcon(true, false); DirectoryInfo directoryInfo = new DirectoryInfo(Path.Combine(currentPath, directory.Name)); TreeNode node = (TreeNode)this.Invoke(this.addTreeNodeCallback, new object[] { nodes, folderIcon, directory.Name, directoryInfo, false }); folderIcon.Dispose(); // add sub-directories and files to this node nodes = node.Nodes; currentPath = Path.Combine(currentPath, directory.Name); } foreach (Wix.ISchemaElement element in directory.Children) { Wix.Component component = element as Wix.Component; if (null != component) { foreach (Wix.ISchemaElement child in component.Children) { Wix.File file = child as Wix.File; if (null != file) { bool selected = false; FileInfo fileInfo = new FileInfo(Path.Combine(currentPath, file.Name)); // if there is no application entry point and we've found an executable make this the application entry point if (this.packageBuilder.ApplicationEntry == null && String.Compare(fileInfo.Extension, ".exe", true, CultureInfo.InvariantCulture) == 0) { //this.packageBuilder.ApplicationEntry = fileInfo.FullName.Substring(rootDirectory.FullName.Length + 1); selected = true; } // get the file icon, add it to the image list, then free it immediately Icon fileIcon = NativeMethods.GetFileIcon(fileInfo.FullName, true, false); this.Invoke(this.addTreeNodeCallback, new object[] { nodes, fileIcon, file.Name, fileInfo, selected }); fileIcon.Dispose(); } } } else { Wix.Directory subDirectory = element as Wix.Directory; if (null != subDirectory) { this.AddDirectory(nodes, currentPath, rootDirectory, subDirectory, false); } } } }
/// <summary> /// 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); }
/// <summary> /// Harvests the satellite files for an assembly. /// </summary> /// <param name="sFileLocalName">Local name (without path, but with extension) of the file to seek for.</param> /// <param name="errorlevel">How to treat the missing file.</param> /// <param name="sSatelliteDisplayName">Display name of the satellite to be included into the error message.</param> /// <param name="wixparent">The parent component to mount the new entry into.</param> /// <param name="assemblyxml">The assembly for which we're seeking for satellites.</param> private void HarvestSatellite(AssemblyXml assemblyxml, string sFileLocalName, IParentElement wixparent, MissingSatelliteErrorLevel errorlevel, string sSatelliteDisplayName, Dictionary <string, string> mapTargetFiles) { if (sFileLocalName == null) { throw new ArgumentNullException("sFileLocalName"); } if (sSatelliteDisplayName == null) { throw new ArgumentNullException("sSatelliteDisplayName"); } if (wixparent == null) { throw new ArgumentNullException("wixparent"); } // Full path var fi = new FileInfo(Path.Combine(Bag.GetString(AttributeName.ProductBinariesDir), sFileLocalName)); // Missing? if (!fi.Exists) { string sErrorMessage = string.Format("Could not locate the {2} for the “{0}” assembly. The expected full path is “{1}”.", assemblyxml.Include, fi.FullName, sSatelliteDisplayName); switch (errorlevel) { case MissingSatelliteErrorLevel.None: break; // Ignore case MissingSatelliteErrorLevel.Warning: Log.LogWarning(sErrorMessage); break; case MissingSatelliteErrorLevel.Error: throw new InvalidOperationException(sErrorMessage); default: throw new ArgumentOutOfRangeException("errorlevel", errorlevel, "Oops."); } return; } // Create an entry var wixFile = new File(); wixparent.AddChild(wixFile); wixFile.Id = string.Format("{0}{1}", FileIdPrefix, fi.Name); wixFile.Name = fi.Name; wixFile.KeyPath = YesNoType.no; wixFile.Checksum = YesNoType.no; wixFile.Vital = YesNoType.no; RegisterTargetFile(wixFile.Name, string.Format("Satellite for the {0} product assembly.", assemblyxml.Include), mapTargetFiles); }
/// <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> /// Decompile the HelpFile table. /// </summary> /// <param name="table">The table to decompile.</param> private void DecompileHelpFileTable(Table table) { foreach (Row row in table.Rows) { VS.HelpFile helpFile = new VS.HelpFile(); helpFile.Id = (string)row[0]; helpFile.Name = (string)row[1]; if (null != row[2]) { helpFile.Language = (int)row[2]; } if (null != row[4]) { helpFile.Index = (string)row[4]; } if (null != row[5]) { helpFile.Search = (string)row[5]; } if (null != row[6]) { helpFile.AttributeIndex = (string)row[6]; } if (null != row[7]) { helpFile.SampleLocation = (string)row[7]; } if (this.Core.RootElement is Wix.Module) { helpFile.SuppressCustomActions = VS.YesNoType.yes; } Wix.File file = (Wix.File) this.Core.GetIndexedElement("File", (string)row[3]); if (null != file) { file.AddChild(helpFile); } else { this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerCore.PrimaryKeyDelimiter), "File_HxS", (string)row[3], "File")); } } }
/// <summary> /// Returns the File matching the relative path in the Directory tree. /// </summary> /// <param name="relativePath">Relative path to the file to find in the directory.</param> /// <param name="directory">Directory tree to search for relative path in.</param> private Wix.File GetFile(string relativePath, Wix.Directory rootDirectory) { IEnumerable enumerable = rootDirectory.Children; string[] directory = relativePath.Split(Path.DirectorySeparatorChar); for (int i = 0; i < directory.Length; ++i) { bool found = false; if (i < directory.Length - 1) { foreach (Wix.ISchemaElement element in enumerable) { Wix.Directory childDirectory = element as Wix.Directory; if (null != childDirectory && directory[i] == childDirectory.Name) { enumerable = childDirectory.Children; found = true; break; } } } else { foreach (Wix.ISchemaElement element in enumerable) { Wix.Component component = element as Wix.Component; if (null != component) { foreach (Wix.ISchemaElement child in component.Children) { Wix.File file = child as Wix.File; if (null != file && directory[i] == file.Name) { return(file); } } } } } if (!found) { throw new ApplicationException("Did not find file name"); } } return(null); }
/// <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 void LoadTlb(Artifact artifact, string rootFolderPath, Component component) { // Create a file. File file = CreateFile(artifact.ProjectRelativePath, FilePath.GetAbsolutePath(artifact.ProjectRelativePath, rootFolderPath)); component.AddChild(file); file.KeyPath = YesNoType.yes; // Check for extra registration. if (artifact.GetBooleanMetadata(Constants.Catalogue.Artifact.Register)) { RegisterTypeLib(artifact, rootFolderPath, component); } }
/// <summary> /// Harvest a file. /// </summary> /// <param name="path">The path of the file.</param> /// <returns>A harvested file.</returns> public Wix.File HarvestFile(string path) { if (null == path) { throw new ArgumentNullException("path"); } Wix.File file = new Wix.File(); // use absolute paths path = Path.GetFullPath(path); file.KeyPath = Wix.YesNoType.yes; file.Name = Path.GetFileName(path); file.Source = path; return(file); }
private static void InvokeWixRedirector(FileInfo fi, File wixFile, Component wixComponent, Action onInvokeSelfReg) { RegistryValue[] values; using (new WixRegistryHarvester(true)) { onInvokeSelfReg(); values = WixRegistryHarvester.HarvestRegistry(); } // Proper roots, file refs TranslateValues(values, wixFile, fi); // Mount foreach (RegistryValue value in values) { wixComponent.AddChild(value); } }
private void LoadDefault(Artifact artifact, string rootFolderPath, Directory directory, Component component) { // Create a file. File file = CreateFile(artifact.ProjectRelativePath, FilePath.GetAbsolutePath(artifact.ProjectRelativePath, rootFolderPath)); component.AddChild(file); // Check for short cuts. string shortcutName = artifact.GetMetadata(Constants.Catalogue.Artifact.ShortcutName); string shortcutPath = artifact.GetMetadata(Constants.Catalogue.Artifact.ShortcutPath); if (!string.IsNullOrEmpty(shortcutName) || !string.IsNullOrEmpty(shortcutPath)) { CreateShortcut(artifact, directory, shortcutName, shortcutPath, file); } }
/// <summary> /// Decompile the WixGameExplorer table. /// </summary> /// <param name="table">The table to decompile.</param> private void DecompileWixGameExplorerTable(Table table) { foreach (Row row in table.Rows) { Gaming.Game game = new Gaming.Game(); game.Id = (string)row[0]; Wix.File file = (Wix.File) this.Core.GetIndexedElement("File", (string)row[1]); if (null != file) { file.AddChild(game); } else { this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerCore.PrimaryKeyDelimiter), "File_", (string)row[1], "File")); } } }
/// <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"); // 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 file. /// </summary> /// <param name="path">The path of the file.</param> /// <returns>A harvested file.</returns> public Wix.File HarvestFile(string path) { if (null == path) { throw new ArgumentNullException("path"); } if (!File.Exists(path)) { throw new WixException(UtilErrors.FileNotFound(path)); } Wix.File file = new Wix.File(); // use absolute paths path = Path.GetFullPath(path); file.KeyPath = Wix.YesNoType.yes; file.Source = String.Concat("SourceDir\\", Path.GetFileName(path)); return(file); }
/// <summary> /// Decompile the File table. /// </summary> /// <param name="table">The table to decompile.</param> private void DecompileFileTable(Table table) { foreach (FileRow fileRow in table.Rows) { Wix.File file = new Wix.File(); file.Id = fileRow.File; string[] names = Installer.GetNames(fileRow.FileName); if (null != names[0] && null != names[1]) { file.ShortName = names[0]; file.Name = names[1]; } else if (null != names[0]) { file.Name = names[0]; } if (null != fileRow.Version && 0 < fileRow.Version.Length) { if (!Char.IsDigit(fileRow.Version[0])) { file.CompanionFile = fileRow.Version; } } if (MsiInterop.MsidbFileAttributesReadOnly == (fileRow.Attributes & MsiInterop.MsidbFileAttributesReadOnly)) { file.ReadOnly = Wix.YesNoType.yes; } if (MsiInterop.MsidbFileAttributesHidden == (fileRow.Attributes & MsiInterop.MsidbFileAttributesHidden)) { file.Hidden = Wix.YesNoType.yes; } if (MsiInterop.MsidbFileAttributesSystem == (fileRow.Attributes & MsiInterop.MsidbFileAttributesSystem)) { file.System = Wix.YesNoType.yes; } if (MsiInterop.MsidbFileAttributesVital != (fileRow.Attributes & MsiInterop.MsidbFileAttributesVital)) { file.Vital = Wix.YesNoType.no; } if (MsiInterop.MsidbFileAttributesChecksum == (fileRow.Attributes & MsiInterop.MsidbFileAttributesChecksum)) { file.Checksum = Wix.YesNoType.yes; } if (MsiInterop.MsidbFileAttributesNoncompressed == (fileRow.Attributes & MsiInterop.MsidbFileAttributesNoncompressed) && MsiInterop.MsidbFileAttributesCompressed == (fileRow.Attributes & MsiInterop.MsidbFileAttributesCompressed)) { // TODO: error } else if (MsiInterop.MsidbFileAttributesNoncompressed == (fileRow.Attributes & MsiInterop.MsidbFileAttributesNoncompressed)) { file.Compressed = Wix.YesNoDefaultType.no; } else if (MsiInterop.MsidbFileAttributesCompressed == (fileRow.Attributes & MsiInterop.MsidbFileAttributesCompressed)) { file.Compressed = Wix.YesNoDefaultType.yes; } this.core.IndexElement(fileRow, file); } }
/// <summary> /// Creates the shim component. /// </summary> /// <returns>Component for the shim.</returns> private Wix.Component GenerateShimComponent() { Wix.Component shimComponent = new Wix.Component(); if (Guid.Empty == this.shimGuid) { this.shimGuid = Guid.NewGuid(); } shimComponent.Id = "ThisApplicationShimDllComponent"; shimComponent.Guid = this.shimGuid.ToString("B"); Wix.File file = new Wix.File(); file.Id = "ThisApplicationShimDll"; file.Name = String.Concat(Path.GetFileNameWithoutExtension(this.entryFileRelativePath), "Shim.dll"); file.Vital = Wix.YesNoType.yes; file.KeyPath = Wix.YesNoType.yes; file.Source = this.shimPath; shimComponent.AddChild(file); // Add the CLSID and ProgId to the component. Wix.Class classId = new Wix.Class(); classId.Id = this.ShimClsid.ToString("B"); classId.Context = Wix.Class.ContextType.InprocServer32; if (null != this.Description && String.Empty != this.Description) { classId.Description = this.Description; } classId.ThreadingModel = Wix.Class.ThreadingModelType.apartment; file.AddChild(classId); Wix.ProgId progId = new Wix.ProgId(); progId.Id = this.ShimProgid; progId.Description = "Connect Class"; classId.AddChild(progId); // Add the Addin to the extended Office applications. foreach (OfficeAddinFabricator.OfficeApplications extendedOfficeApp in this.extendedOfficeApplications) { Wix.RegistryKey registryKey = new Wix.RegistryKey(); registryKey.Root = Wix.RegistryRootType.HKMU; registryKey.Key = String.Format("Software\\Microsoft\\Office\\{0}\\Addins\\{1}", OfficeAddinFabricator.OfficeApplicationStrings[(int)extendedOfficeApp], this.ShimProgid); shimComponent.AddChild(registryKey); Wix.RegistryValue registryValue = new Wix.RegistryValue(); registryValue.Name = "Description"; registryValue.Value = "[ProductName] v[ProductVersion]"; registryValue.Type = Wix.RegistryValue.TypeType.@string; registryKey.AddChild(registryValue); registryValue = new Wix.RegistryValue(); registryValue.Name = "FriendlyName"; registryValue.Value = "[ProductName]"; registryValue.Type = Wix.RegistryValue.TypeType.@string; registryKey.AddChild(registryValue); registryValue = new Wix.RegistryValue(); registryValue.Name = "LoadBehavior"; registryValue.Value = "3"; registryValue.Type = Wix.RegistryValue.TypeType.integer; registryKey.AddChild(registryValue); } return(shimComponent); }
/// <summary> /// Harvest a file. /// </summary> /// <param name="path">The path of the file.</param> /// <returns>A harvested file.</returns> public Wix.File HarvestFile(string path) { if (null == path) { throw new ArgumentNullException("path"); } if (!File.Exists(path)) { throw new WixException(UtilErrors.FileNotFound(path)); } Wix.File file = new Wix.File(); // use absolute paths path = Path.GetFullPath(path); file.KeyPath = Wix.YesNoType.yes; file.Source = String.Concat("SourceDir\\", Path.GetFileName(path)); return file; }
/// <summary> /// Returns a Shortcut for each Component in the Directory tree. /// </summary> /// <param name="">The root Directory of the components.</param> private Wix.Shortcut GetShortcut(string relativePath, Wix.Directory directory, Wix.Directory shortcutDirectory) { Wix.Shortcut shortcut = null; IEnumerable enumerable = directory.Children; string[] dir = relativePath.Split(Path.DirectorySeparatorChar); for (int i = 0; i < dir.Length; ++i) { bool found = false; if (i < dir.Length - 1) { foreach (Wix.ISchemaElement element in enumerable) { if (element is Wix.Directory) { Wix.Directory dirx = (Wix.Directory)element; if (dir[i] == dirx.LongName) { enumerable = dirx.Children; found = true; break; } } } } else { foreach (Wix.ISchemaElement element in enumerable) { if (element is Wix.Component) { enumerable = ((Wix.Component)element).Children; foreach (Wix.ISchemaElement elementx in enumerable) { if (elementx is Wix.File) { Wix.File fil = (Wix.File)elementx; if (dir[i] == fil.LongName) { shortcut = new Wix.Shortcut(); shortcut.Id = String.Concat(fil.Id, "Shortcut"); shortcut.Directory = shortcutDirectory.Id; shortcut.Target = "[!SystemApplicationUpdateExeFile]"; shortcut.Name = "shortcu1"; shortcut.LongName = Path.GetFileNameWithoutExtension(fil.LongName); shortcut.Arguments = String.Format(CultureInfo.InvariantCulture, "-ac [UpgradeCode] -cl \"[#{0}]\"", fil.Id); found = true; break; } } } } if (found) { break; } } } if (!found) { throw new ApplicationException("did not find file name"); } } return(shortcut); }
/// <summary> /// Harvest files from one output group of a VS project. /// </summary> /// <param name="baseDir">The base directory of the files.</param> /// <param name="projectName">Name of the project, to be used as a prefix for generated identifiers.</param> /// <param name="pogName">Name of the project output group, used for generating identifiers for WiX elements.</param> /// <param name="pogFileSource">The ProjectOutputGroup file source.</param> /// <param name="outputGroupFiles">The files from one output group to harvest.</param> /// <param name="parent">The parent element that will contain the components of the harvested files.</param> /// <returns>The number of files harvested.</returns> private int HarvestProjectOutputGroupFiles(string baseDir, string projectName, string pogName, string pogFileSource, IEnumerable outputGroupFiles, Wix.IParentElement parent) { int fileCount = 0; Wix.ISchemaElement exeFile = null; Wix.ISchemaElement appConfigFile = null; // Keep track of files inserted // Files can have different absolute paths but get mapped to the same SourceFile // after the project variables have been used. For example, a WiX project that // is building multiple cultures will have many output MSIs/MSMs, but will all get // mapped to $(var.ProjName.TargetDir)\ProjName.msm. These duplicates would // prevent generated code from compiling. Dictionary<string, bool> seenList = new Dictionary<string,bool>(); foreach (object output in outputGroupFiles) { string filePath = output.ToString(); string fileName = Path.GetFileName(filePath); string fileDir = Path.GetDirectoryName(filePath); string link = null; MethodInfo getMetadataMethod = output.GetType().GetMethod("GetMetadata"); if (getMetadataMethod != null) { link = (string)getMetadataMethod.Invoke(output, new object[] { "Link" }); if (!String.IsNullOrEmpty(link)) { fileDir = Path.GetDirectoryName(Path.Combine(baseDir, link)); } } Wix.IParentElement parentDir = parent; // Ignore Containers and PayloadGroups because they do not have a nested structure. if (baseDir != null && !String.Equals(Path.GetDirectoryName(baseDir), fileDir, StringComparison.OrdinalIgnoreCase) && this.GenerateType != GenerateType.Container && this.GenerateType != GenerateType.PackageGroup && this.GenerateType != GenerateType.PayloadGroup) { Uri baseUri = new Uri(baseDir); Uri relativeUri = baseUri.MakeRelativeUri(new Uri(fileDir)); parentDir = this.GetSubDirElement(parentDir, relativeUri); } string parentDirId = null; if (parentDir is Wix.DirectoryRef) { parentDirId = this.directoryRefSeed; } else if (parentDir is Wix.Directory) { parentDirId = ((Wix.Directory)parentDir).Id; } if (this.GenerateType == GenerateType.Container || this.GenerateType == GenerateType.PayloadGroup) { Wix.Payload payload = new Wix.Payload(); HarvestProjectOutputGroupPayloadFile(baseDir, projectName, pogName, pogFileSource, filePath, fileName, link, parentDir, payload, seenList); } else if (this.GenerateType == GenerateType.PackageGroup) { HarvestProjectOutputGroupPackage(projectName, pogName, pogFileSource, filePath, fileName, link, parentDir, seenList); } else { Wix.Component component = new Wix.Component(); Wix.File file = new Wix.File(); HarvestProjectOutputGroupFile(baseDir, projectName, pogName, pogFileSource, filePath, fileName, link, parentDir, parentDirId, component, file, seenList); if (String.Equals(Path.GetExtension(file.Source), ".exe", StringComparison.OrdinalIgnoreCase)) { exeFile = file; } else if (file.Source.EndsWith("app.config", StringComparison.OrdinalIgnoreCase)) { appConfigFile = file; } } fileCount++; } // Special case for the app.config file in the Binaries POG... // The POG refers to the files in the OBJ directory, while the // generated WiX code references them in the bin directory. // The app.config file gets renamed to match the exe name. if ("Binaries" == pogName && null != exeFile && null != appConfigFile) { if (appConfigFile is Wix.File) { Wix.File appConfigFileAsWixFile = appConfigFile as Wix.File; Wix.File exeFileAsWixFile = exeFile as Wix.File; // Case insensitive replace appConfigFileAsWixFile.Source = Regex.Replace(appConfigFileAsWixFile.Source, @"app\.config", Path.GetFileName(exeFileAsWixFile.Source) + ".config", RegexOptions.IgnoreCase); } } return fileCount; }
/// <summary> /// Harvest a directory. /// </summary> /// <param name="path">The path of the directory.</param> /// <param name="relativePath">The relative path that will be used when harvesting.</param> /// <param name="directory">The directory for this path.</param> /// <returns>The number of files harvested.</returns> private int HarvestDirectory(string path, string relativePath, Wix.Directory directory) { int fileCount = 0; // harvest the child directories foreach (string childDirectoryPath in Directory.GetDirectories(path)) { Wix.Directory childDirectory = new Wix.Directory(); childDirectory.Name = Path.GetFileName(childDirectoryPath); childDirectory.FileSource = childDirectoryPath; if (this.setUniqueIdentifiers) { childDirectory.Id = this.Core.GenerateIdentifier(DirectoryPrefix, directory.Id, childDirectory.Name); } int childFileCount = this.HarvestDirectory(childDirectoryPath, String.Concat(relativePath, childDirectory.Name, "\\"), childDirectory); // keep the directory if it contained any files (or empty directories are being kept) if (0 < childFileCount || this.keepEmptyDirectories) { directory.AddChild(childDirectory); } fileCount += childFileCount; } // harvest the files string[] files = Directory.GetFiles(path); if (0 < files.Length) { foreach (string filePath in Directory.GetFiles(path)) { string fileName = Path.GetFileName(filePath); Wix.Component component = new Wix.Component(); Wix.File file = this.fileHarvester.HarvestFile(filePath); file.Source = String.Concat(relativePath, fileName); if (this.setUniqueIdentifiers) { file.Id = this.Core.GenerateIdentifier(FilePrefix, directory.Id, fileName); component.Id = this.Core.GenerateIdentifier(ComponentPrefix, directory.Id, file.Id); } component.AddChild(file); directory.AddChild(component); } } else if (0 == fileCount && this.keepEmptyDirectories) { Wix.Component component = new Wix.Component(); component.KeyPath = Wix.YesNoType.yes; if (this.setUniqueIdentifiers) { component.Id = this.Core.GenerateIdentifier(ComponentPrefix, directory.Id); } Wix.CreateFolder createFolder = new Wix.CreateFolder(); component.AddChild(createFolder); directory.AddChild(component); } return(fileCount + files.Length); }
/// <summary> /// Creates the shim component. /// </summary> /// <returns>Component for the shim.</returns> private Wix.Component GenerateShimComponent() { Wix.Component shimComponent = new Wix.Component(); if (Guid.Empty == this.shimGuid) { this.shimGuid = Guid.NewGuid(); } shimComponent.Id = "ThisApplicationShimDllComponent"; shimComponent.Guid = this.shimGuid.ToString("B"); Wix.File file = new Wix.File(); file.Id = "ThisApplicationShimDll"; file.Name = String.Concat(Path.GetFileNameWithoutExtension(this.entryFileRelativePath), "Shim.dll"); file.Vital = Wix.YesNoType.yes; file.KeyPath = Wix.YesNoType.yes; file.Source = this.shimPath; shimComponent.AddChild(file); // Add the CLSID and ProgId to the component. Wix.Class classId = new Wix.Class(); classId.Id = this.ShimClsid.ToString("B"); classId.Context = Wix.Class.ContextType.InprocServer32; if (null != this.Description && String.Empty != this.Description) { classId.Description = this.Description; } classId.ThreadingModel = Wix.Class.ThreadingModelType.apartment; file.AddChild(classId); Wix.ProgId progId = new Wix.ProgId(); progId.Id = this.ShimProgid; progId.Description = "Connect Class"; classId.AddChild(progId); // Add the Addin to the extended Office applications. foreach (OfficeAddinFabricator.OfficeApplications extendedOfficeApp in this.extendedOfficeApplications) { Wix.RegistryKey registryKey = new Wix.RegistryKey(); registryKey.Root = Wix.RegistryRootType.HKMU; registryKey.Key = String.Format("Software\\Microsoft\\Office\\{0}\\Addins\\{1}", OfficeAddinFabricator.OfficeApplicationStrings[(int)extendedOfficeApp], this.ShimProgid); shimComponent.AddChild(registryKey); Wix.RegistryValue registryValue = new Wix.RegistryValue(); registryValue.Name = "Description"; registryValue.Value = "[ProductName] v[ProductVersion]"; registryValue.Type = Wix.RegistryValue.TypeType.@string; registryKey.AddChild(registryValue); registryValue = new Wix.RegistryValue(); registryValue.Name = "FriendlyName"; registryValue.Value = "[ProductName]"; registryValue.Type = Wix.RegistryValue.TypeType.@string; registryKey.AddChild(registryValue); registryValue = new Wix.RegistryValue(); registryValue.Name = "LoadBehavior"; registryValue.Value = "3"; registryValue.Type = Wix.RegistryValue.TypeType.integer; registryKey.AddChild(registryValue); } return shimComponent; }
/// <summary> /// Gets the file object for the ApplicationEntry. /// </summary> public Wix.File GetApplicationEntryFile() { if (null != this.applicationRoot && null != this.applicationEntry.Content && null == this.applicationEntryFile) { Wix.Directory applicationDir = this.GetApplicationRootDirectory(); this.applicationEntryFile = this.GetFile(this.applicationEntry.Content, this.applicationRootDirectory); } return this.applicationEntryFile; }