/// <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(DecompilerConstants.PrimaryKeyDelimiter), "File_Collection", (string)row[2], "File")); } this.Core.IndexElement(row, helpCollection); } }
/// <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); }
/// <summary> /// Add a scraped directory to the UI. /// </summary> /// <param name="nodes">The NodeCollection under which the new directory should be added.</param> /// <param name="rootDirectory">Root of the scraped directory info's.</param> /// <param name="directory">The scraped directory to add.</param> /// <param name="skip">true if the directory itself shouldn't be added; false otherwise.</param> private void AddDirectory(TreeNodeCollection nodes, string currentPath, Wix.Directory rootDirectory, Wix.Directory directory, bool skip) { // get the directory icon, add it to the image list, then free it immediately if (!skip) { Icon folderIcon = NativeMethods.GetDirectoryIcon(true, false); DirectoryInfo directoryInfo = new DirectoryInfo(Path.Combine(currentPath, directory.Name)); TreeNode node = (TreeNode)this.Invoke(this.addTreeNodeCallback, new object[] { nodes, folderIcon, directory.Name, directoryInfo, false }); folderIcon.Dispose(); // add sub-directories and files to this node nodes = node.Nodes; currentPath = Path.Combine(currentPath, directory.Name); } foreach (Wix.ISchemaElement element in directory.Children) { Wix.Component component = element as Wix.Component; if (null != component) { foreach (Wix.ISchemaElement child in component.Children) { Wix.File file = child as Wix.File; if (null != file) { bool selected = false; FileInfo fileInfo = new FileInfo(Path.Combine(currentPath, file.Name)); // if there is no application entry point and we've found an executable make this the application entry point if (this.packageBuilder.ApplicationEntry == null && String.Compare(fileInfo.Extension, ".exe", true, CultureInfo.InvariantCulture) == 0) { //this.packageBuilder.ApplicationEntry = fileInfo.FullName.Substring(rootDirectory.FullName.Length + 1); selected = true; } // get the file icon, add it to the image list, then free it immediately Icon fileIcon = NativeMethods.GetFileIcon(fileInfo.FullName, true, false); this.Invoke(this.addTreeNodeCallback, new object[] { nodes, fileIcon, file.Name, fileInfo, selected }); fileIcon.Dispose(); } } } else { Wix.Directory subDirectory = element as Wix.Directory; if (null != subDirectory) { this.AddDirectory(nodes, currentPath, rootDirectory, subDirectory, false); } } } }
/// <summary> /// Returns the File matching the relative path in the Directory tree. /// </summary> /// <param name="rootDirectory">Directory tree to search for relative path in.</param> /// <param name="relativePath">Relative path to the file to find in the directory.</param> /// <returns>File at relativePath in rootDirectory.</returns> private Wix.File GetFile(Wix.Directory rootDirectory, string relativePath) { 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> /// 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(DecompilerConstants.PrimaryKeyDelimiter), "File_HxS", (string)row[3], "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> /// Generates the .wxs file for the application. /// </summary> /// <returns>XmlDocument containing the .wxs file for the application.</returns> private XmlDocument GenerateSourceFile() { XmlDocument sourceDoc = null; // Ensure the root application directory has been calculated and the // new PackageCode is generated. this.GetRootDirectory(false); this.productCode = Guid.NewGuid(); // Build up the product information. Wix.Wix wix = new Wix.Wix(); Wix.Product product = new Wix.Product(); product.Id = this.productCode.ToString(); product.Language = this.language; product.Manufacturer = this.manufacturer; product.Name = this.name; product.UpgradeCode = this.upgradeCode.ToString(); product.Version = this.version.ToString(); wix.AddChild(product); Wix.Package package = new Wix.Package(); package.Compressed = Wix.YesNoType.yes; if (null != this.description) { package.Description = this.description; } package.InstallerVersion = 200; package.InstallPrivileges = Wix.Package.InstallPrivilegesType.limited; product.AddChild(package); Wix.WixVariable variable = new Wix.WixVariable(); variable = new Wix.WixVariable(); variable.Id = "ProductName"; variable.Value = product.Name; product.AddChild(variable); variable = new Wix.WixVariable(); variable.Id = "ProductCode"; variable.Value = product.Id; product.AddChild(variable); variable = new Wix.WixVariable(); variable.Id = "ProductVersion"; variable.Value = product.Version; product.AddChild(variable); // Find the entry File/@Id for the Shortcut to point at. Wix.File entryFile = this.GetFile(this.rootDirectory, this.entryFileRelativePath); variable = new Wix.WixVariable(); variable.Id = "ShortcutFileId"; variable.Value = entryFile.Id; product.AddChild(variable); // Set the target Component's GUID to be the same as the ProductCode for easy // lookup by the update.exe. Wix.Component targetComponent = (Wix.Component)entryFile.ParentElement; targetComponent.Guid = product.Id; variable = new Wix.WixVariable(); variable.Id = "TargetComponentId"; variable.Value = targetComponent.Guid; product.AddChild(variable); // Upgrade logic. Wix.Upgrade upgrade = new Wix.Upgrade(); upgrade.Id = product.UpgradeCode; product.AddChild(upgrade); Wix.UpgradeVersion minUpgrade = new Wix.UpgradeVersion(); minUpgrade.Minimum = product.Version; minUpgrade.OnlyDetect = Wix.YesNoType.yes; minUpgrade.Property = "NEWERVERSIONDETECTED"; upgrade.AddChild(minUpgrade); Wix.UpgradeVersion maxUpgrade = new Wix.UpgradeVersion(); maxUpgrade.Maximum = product.Version; maxUpgrade.IncludeMaximum = Wix.YesNoType.no; maxUpgrade.Property = "OLDERVERSIONBEINGUPGRADED"; upgrade.AddChild(maxUpgrade); // Update feed property. Wix.Property property = new Wix.Property(); property.Id = "ARPURLUPDATEINFO"; property.Value = this.updateUrl.AbsoluteUri; product.AddChild(property); // Root the application's directory tree in the applications folder. Wix.DirectoryRef applicationsFolderRef = new Wix.DirectoryRef(); applicationsFolderRef.Id = "ApplicationsFolder"; product.AddChild(applicationsFolderRef); this.rootDirectory.Name = String.Concat(product.Id, "v", product.Version); applicationsFolderRef.AddChild(this.rootDirectory); // Add all of the Components to the Feature tree. Wix.FeatureRef applicationFeatureRef = new Wix.FeatureRef(); applicationFeatureRef.Id = "ApplicationFeature"; product.AddChild(applicationFeatureRef); Wix.ComponentRef[] componentRefs = this.GetComponentRefs(this.rootDirectory); foreach (Wix.ComponentRef componentRef in componentRefs) { applicationFeatureRef.AddChild(componentRef); } // Serialize product information to an xml string. string xml; using (StringWriter sw = new StringWriter()) { XmlTextWriter writer = null; try { writer = new XmlTextWriter(sw); wix.OutputXml(writer); xml = sw.ToString(); } finally { if (writer != null) { writer.Close(); } } } // Load the xml into a document. sourceDoc = new XmlDocument(); sourceDoc.LoadXml(xml); return(sourceDoc); }
/// <summary> /// Decompile the NetFxNativeImage table. /// </summary> /// <param name="table">The table to decompile.</param> private void DecompileNetFxNativeImageTable(Table table) { foreach (Row row in table.Rows) { NetFx.NativeImage nativeImage = new NetFx.NativeImage(); nativeImage.Id = (string)row[0]; switch ((int)row[2]) { case 0: nativeImage.Priority = NetFx.NativeImage.PriorityType.Item0; break; case 1: nativeImage.Priority = NetFx.NativeImage.PriorityType.Item1; break; case 2: nativeImage.Priority = NetFx.NativeImage.PriorityType.Item2; break; case 3: nativeImage.Priority = NetFx.NativeImage.PriorityType.Item3; break; } if (null != row[3]) { int attributes = (int)row[3]; if (0x1 == (attributes & 0x1)) { nativeImage.Debug = NetFx.YesNoType.yes; } if (0x2 == (attributes & 0x2)) { nativeImage.Dependencies = NetFx.YesNoType.no; } if (0x4 == (attributes & 0x4)) { nativeImage.Profile = NetFx.YesNoType.yes; } if (0x8 == (attributes & 0x8) && 0x10 == (attributes & 0x10)) { nativeImage.Platform = NetFx.NativeImage.PlatformType.all; } else if (0x8 == (attributes & 0x8)) { nativeImage.Platform = NetFx.NativeImage.PlatformType.Item32bit; } else if (0x10 == (attributes & 0x10)) { nativeImage.Platform = NetFx.NativeImage.PlatformType.Item64bit; } } if (null != row[4]) { nativeImage.AssemblyApplication = (string)row[4]; } if (null != row[5]) { nativeImage.AppBaseDirectory = (string)row[5]; } Wix.File file = (Wix.File) this.Core.GetIndexedElement("File", (string)row[1]); if (null != file) { file.AddChild(nativeImage); } else { this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "File_", (string)row[1], "File")); } } }
/// <summary> /// Mutate a file. /// </summary> /// <param name="parentElement">The parent of the element to mutate.</param> /// <param name="file">The file to mutate.</param> private void MutateFile(Wix.IParentElement parentElement, Wix.File file) { if (null != file.Source) { string fileExtension = Path.GetExtension(file.Source); string fileSource = this.Core.ResolveFilePath(file.Source); if (String.Equals(".ax", fileExtension, StringComparison.OrdinalIgnoreCase) || // DirectShow filter String.Equals(".dll", fileExtension, StringComparison.OrdinalIgnoreCase) || String.Equals(".exe", fileExtension, StringComparison.OrdinalIgnoreCase) || String.Equals(".ocx", fileExtension, StringComparison.OrdinalIgnoreCase)) // ActiveX { // try the assembly harvester try { AssemblyHarvester assemblyHarvester = new AssemblyHarvester(); this.Core.OnMessage(UtilVerboses.HarvestingAssembly(fileSource)); Wix.RegistryValue[] registryValues = assemblyHarvester.HarvestRegistryValues(fileSource); foreach (Wix.RegistryValue registryValue in registryValues) { parentElement.AddChild(registryValue); } // also try self-reg since we could have a mixed-mode assembly this.HarvestSelfReg(parentElement, fileSource); } catch (BadImageFormatException) // not an assembly, try raw DLL. { this.HarvestSelfReg(parentElement, fileSource); } catch (Exception ex) { this.Core.OnMessage(UtilWarnings.AssemblyHarvestFailed(fileSource, ex.Message)); } } else if (String.Equals(".olb", fileExtension, StringComparison.OrdinalIgnoreCase) || // type library String.Equals(".tlb", fileExtension, StringComparison.OrdinalIgnoreCase)) // type library { // try the type library harvester try { TypeLibraryHarvester typeLibHarvester = new TypeLibraryHarvester(); this.Core.OnMessage(UtilVerboses.HarvestingTypeLib(fileSource)); Wix.RegistryValue[] registryValues = typeLibHarvester.HarvestRegistryValues(fileSource); foreach (Wix.RegistryValue registryValue in registryValues) { parentElement.AddChild(registryValue); } } catch (COMException ce) { // 0x8002801C (TYPE_E_REGISTRYACCESS) // If we don't have permission to harvest typelibs, it's likely because we're on // Vista or higher and aren't an Admin, or don't have the appropriate QFE installed. if (!this.calledPerUserTLibReg && (0x8002801c == unchecked ((uint)ce.ErrorCode))) { this.Core.OnMessage(WixWarnings.InsufficientPermissionHarvestTypeLib()); } else if (0x80029C4A == unchecked ((uint)ce.ErrorCode)) // generic can't load type library { this.Core.OnMessage(UtilWarnings.TypeLibLoadFailed(fileSource, ce.Message)); } } } } }
/// <summary> /// 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> /// 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 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); }