Skip to content

Instantly share code, notes, and snippets.

@cathode
Created August 12, 2016 15:23
Show Gist options
  • Save cathode/20b722e65dcccfc18c578ae2cfd98e2f to your computer and use it in GitHub Desktop.
Save cathode/20b722e65dcccfc18c578ae2cfd98e2f to your computer and use it in GitHub Desktop.
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