Created
August 12, 2016 15:23
-
-
Save cathode/20b722e65dcccfc18c578ae2cfd98e2f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using System.Threading.Tasks; | |
using System.IO; | |
using Microsoft.Win32; | |
using System.Runtime.InteropServices; | |
using System.Reflection; | |
using System.Diagnostics.Contracts; | |
namespace RegAsmPlus | |
{ | |
public class AssemblyRegistrar | |
{ | |
public AssemblyRegistrar() | |
{ | |
} | |
public void RegisterAssembly(string asmPath) | |
{ | |
Contract.Requires(asmPath != null); | |
var asm = Assembly.LoadFrom(asmPath); | |
this.RegisterAssembly(asm); | |
} | |
public void RegisterAssembly(Assembly asm) | |
{ | |
Contract.Requires(asm != null); | |
// == Register the typelib == | |
Guid asmId = Marshal.GetTypeLibGuidForAssembly(asm); | |
string codeBase = asm.CodeBase; | |
Version version = asm.GetName().Version; | |
var regBase = Registry.CurrentUser; | |
//#if DEBUG | |
// regBase = regBase.CreateSubKey("DEBUG"); | |
//#endif | |
var topLevelKeys = new List<RegistryKey>(); | |
var keyParents = new List<RegistryKey>(); | |
// Create normal keys | |
keyParents.Add(regBase.CreateSubKey("SOFTWARE\\Classes")); | |
if (Environment.Is64BitOperatingSystem) | |
{ | |
keyParents.Add(regBase.CreateSubKey("SOFTWARE\\WOW6432Node\\Classes")); | |
keyParents.Add(regBase.CreateSubKey("SOFTWARE\\Classes\\WOW6432Node")); | |
} | |
foreach (var parent in keyParents) | |
{ | |
var key = parent.CreateSubKey("TypeLib\\{" + asmId + "}"); | |
topLevelKeys.Add(key); | |
key = key.CreateSubKey("1.0"); | |
key.SetValue("", asm.GetName().Name); | |
// Create win32 subkey for TLB location | |
var subkey = key.CreateSubKey("0\\win32"); | |
subkey.SetValue("", Path.ChangeExtension(codeBase, "tlb")); | |
subkey = key.CreateSubKey("FLAGS"); | |
subkey.SetValue("", "0"); | |
subkey = key.CreateSubKey("HELPDIR"); | |
subkey.SetValue("", Path.GetDirectoryName(codeBase)); | |
} | |
var types = asm.GetExportedTypes(); | |
foreach (var t in types) | |
{ | |
var comvisible = t.GetCustomAttribute<ComVisibleAttribute>(false); | |
if (comvisible == null) | |
continue; // type is not COM-visible, skip to next type. | |
var tid = t.GUID.ToString().ToUpper(); | |
if (t.IsInterface) | |
{ | |
foreach (var parent in keyParents) | |
{ | |
var subkey = parent.CreateSubKey("Interface\\{" + tid + "}"); | |
topLevelKeys.Add(subkey); | |
subkey.SetValue("", t.Name); | |
subkey.CreateSubKey("ProxyStubClsid32").SetValue("", "{00020424-0000-0000-C000-000000000046}"); | |
subkey = subkey.CreateSubKey("TypeLib"); | |
subkey.SetValue("", "{" + asmId + "}"); | |
subkey.SetValue("Version", "1.0"); | |
} | |
} | |
else if (t.IsClass) | |
{ | |
// Add named class key | |
var classParent = regBase.CreateSubKey("SOFTWARE\\Classes\\" + t.FullName); | |
topLevelKeys.Add(classParent); | |
classParent.SetValue("", t.FullName); | |
var subkey = classParent.CreateSubKey("CLSID"); | |
subkey.SetValue("", "{" + tid + "}"); | |
var classParents = new List<RegistryKey>(); | |
if (Environment.Is64BitOperatingSystem) | |
{ | |
classParents.Add(regBase.CreateSubKey("SOFTWARE\\Classes\\WOW6432Node\\CLSID\\{" + tid + "}")); | |
classParents.Add(regBase.CreateSubKey("SOFTWARE\\WOW6432Node\\Classes\\CLSID\\{" + tid + "}")); | |
} | |
else | |
{ | |
classParents.Add(regBase.CreateSubKey("SOFTWARE\\Classes\\CLSID\\{" + tid + "}")); | |
} | |
topLevelKeys.AddRange(classParents); | |
foreach (var parent in classParents) | |
{ | |
parent.SetValue("", t.FullName); | |
subkey = parent.CreateSubKey("InprocServer32"); | |
subkey.SetValue("", "mscoree.dll"); | |
subkey.SetValue("ThreadingModel", "Both"); | |
subkey.SetValue("Class", t.FullName); | |
subkey.SetValue("Assembly", asm.FullName); | |
subkey.SetValue("RuntimeVersion", asm.ImageRuntimeVersion); | |
subkey.SetValue("CodeBase", codeBase); | |
var s2 = subkey.CreateSubKey(version.ToString()); | |
s2.SetValue("Class", t.FullName); | |
s2.SetValue("Assembly", asm.FullName); | |
s2.SetValue("RuntimeVersion", asm.ImageRuntimeVersion); | |
s2.SetValue("CodeBase", codeBase); | |
subkey = parent.CreateSubKey("ProgId"); | |
subkey.SetValue("", t.FullName); | |
} | |
} | |
else if (t.IsEnum) | |
{ | |
// Register enum | |
var subkey = regBase.CreateSubKey("SOFTWARE\\Classes\\Record\\{" + tid + "}"); | |
topLevelKeys.Add(subkey); | |
subkey = subkey.CreateSubKey(version.ToString()); | |
subkey.SetValue("Class", t.FullName); | |
subkey.SetValue("Assembly", asm.FullName); | |
subkey.SetValue("RuntimeVersion", asm.ImageRuntimeVersion); | |
subkey.SetValue("CodeBase", codeBase); | |
} | |
} | |
// Record all the keys that we wrote so they can be undone later. | |
var logKey = regBase.CreateSubKey("SOFTWARE\\AssemblyRegistration\\{" + asmId.ToString().ToUpper() + "}"); | |
var now = DateTime.Now.ToString(); | |
foreach (var k in topLevelKeys) | |
{ | |
logKey.SetValue(k.Name, now); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment