/// /// Copyright © 2003-2008 JetBrains s.r.o. /// You may distribute under the terms of the GNU General Public License, as published by the Free Software Foundation, version 2 (see License.txt in the repository root folder). /// using System.IO; using System.Reflection; using System.Runtime.InteropServices; using System.Text.RegularExpressions; using Microsoft.Tools.WindowsInstallerXml.Serialize; using File=Microsoft.Tools.WindowsInstallerXml.Serialize.File; namespace JetBrains.Build.Omea.Resolved.Infra { /// /// Harvests for Registry data of an assembly, typically that for the COM registration, and produces the WiX Registry entries. /// public static class SelfRegHarvester { #region Data private static readonly bool OptionUnmanagedUseResources = true; #endregion #region Operations public static void Harvest(FileInfo fi, bool managed, Component wixComponent, File wixFile) { if(managed) InvokeWixRedirector(fi, wixFile, wixComponent, delegate { InvokeManagedSelfReg(fi); }); else { if(!OptionUnmanagedUseResources) InvokeWixRedirector(fi, wixFile, wixComponent, delegate { InvokeComSelfReg(fi); }); else NativeSelfRegResourceExtractor.ExtractWxsResource(fi, wixComponent); } } #endregion #region Implementation private static Regex CreateResolveFileRegex(FileInfo fi) { return new Regex(string.Format(@"(file\:/*)?({0}|{1})", Regex.Escape(fi.FullName), Regex.Escape(fi.FullName.Replace('\\', '/'))), RegexOptions.CultureInvariant | RegexOptions.Singleline | RegexOptions.IgnoreCase); } private static void InvokeComSelfReg(FileInfo fi) { using(var pinvoke = new DynamicPinvoke(fi, "DllRegisterServer", typeof(int))) pinvoke.Invoke(); } private static void InvokeManagedSelfReg(FileInfo fi) { Assembly assembly = Assembly.LoadFrom(fi.FullName); // WiX says this helps to prevent binding failures assembly.GetExportedTypes(); new RegistrationServices().RegisterAssembly(assembly, AssemblyRegistrationFlags.SetCodeBase); } 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); } /// /// Takes the values, searches them for the file paths and replaces them with references to the file ID. /// 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); } } #endregion #region Action Type private delegate void Action(); #endregion } }