Skip to content

Instantly share code, notes, and snippets.

@jagt
Last active January 30, 2018 07:41
Show Gist options
  • Save jagt/00a86f32fb0652155787cb6356ad5efb to your computer and use it in GitHub Desktop.
Save jagt/00a86f32fb0652155787cb6356ad5efb to your computer and use it in GitHub Desktop.
publicize.cs
using Mono.Cecil;
using System;
using System.Linq;
using System.Collections.Generic;
// inplace publicize all methods/types in a dll
// need Mono.Cecil in nuget
class Program
{
static void Main(string[] args)
{
if (args.Length < 1)
{
Console.WriteLine("usage: publicize foo.dll");
Environment.Exit(-1);
return;
}
var dllName = args[0];
var dllDef = AssemblyDefinition.ReadAssembly(dllName);
var mainModule = dllDef.MainModule;
foreach (var type in mainModule.GetTypes())
{
ProcessType(type);
}
mainModule.Write(dllName + ".patched");
}
static bool IsCompilerGenerated(IEnumerable<CustomAttribute> customAttributes)
{
return customAttributes.Any(x => x.AttributeType.Name == "CompilerGeneratedAttribute");
}
private static void ProcessType(TypeDefinition typeDefinition)
{
if (IsCompilerGenerated(typeDefinition.CustomAttributes))
{
return;
}
// recur into nested first before any return
foreach (var nestedType in typeDefinition.NestedTypes)
{
ProcessType(nestedType);
}
// it's really cool that 'IsNotPublic' and '!IsPublic' are two completely
// different things. wow.
if (!typeDefinition.IsPublic)
{
if (typeDefinition.IsNested)
{
typeDefinition.IsNestedPublic = true;
}
else
{
typeDefinition.IsPublic = true;
}
Console.WriteLine("Publicize class {0}", typeDefinition.Name);
}
if (typeDefinition.IsInterface)
{
return;
}
foreach (var method in typeDefinition.Methods)
{
ProcessMethod(method);
}
foreach (var field in typeDefinition.Fields)
{
ProcessField(field);
}
}
private static void ProcessMethod(MethodDefinition method)
{
var requiresPublicize = false;
if (method.IsPublic)
{
return;
}
if (method.IsAssembly)
{
method.IsAssembly = false;
requiresPublicize = true;
}
if (method.IsHideBySig)
{
method.IsHideBySig = false;
requiresPublicize = true;
}
if (method.IsPrivate)
{
method.IsPrivate = false;
requiresPublicize = true;
}
if (requiresPublicize)
{
method.IsPublic = true;
Console.WriteLine("Publicize method {0}", method.Name);
}
}
private static void ProcessField(FieldDefinition field)
{
if (IsCompilerGenerated(field.CustomAttributes))
{
return;
}
if (field.IsPublic)
{
return;
}
var requiresPublicize = false;
if (field.IsAssembly)
{
field.IsAssembly = false;
requiresPublicize = true;
}
if (field.IsPrivate)
{
field.IsPrivate = false;
requiresPublicize = true;
}
if (requiresPublicize)
{
field.IsPublic = true;
Console.WriteLine("Publicize field {0}", field.Name);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment