Last active
August 22, 2016 15:21
-
-
Save abombss/5206329 to your computer and use it in GitHub Desktop.
Collect all assembly attributes using a reflection only load of an assembly
This file contains hidden or 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.IO; | |
using System.Linq; | |
using System.Reflection; | |
using System.Security.Policy; | |
namespace MsBuild.AssemblyFu | |
{ | |
internal interface IAssemblyAttributeGetter | |
{ | |
IEnumerable<IEnumerable<KeyValuePair<string, string>>> GetAssemblyAttributes(string assemblyFile); | |
} | |
public class ReflectionOnlyAssemblyAttributeGetter : MarshalByRefObject, IAssemblyAttributeGetter | |
{ | |
public IEnumerable<IEnumerable<KeyValuePair<string, string>>> GetAssemblyAttributes(string assemblyFile) | |
{ | |
var output = new List<IDictionary<string, string>>(); | |
AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += CurrentDomain_ReflectionOnlyAssemblyResolve; | |
try | |
{ | |
var assembly = Assembly.ReflectionOnlyLoadFrom(assemblyFile); | |
var assemblyAttributes = CustomAttributeData.GetCustomAttributes(assembly); | |
output.Add(new Dictionary<string, string>() | |
{ | |
{"AttribFullName", typeof(AssemblyVersionAttribute).FullName}, | |
{"AttribName", typeof(AssemblyVersionAttribute).Name}, | |
{"AttribNamespace", typeof(AssemblyVersionAttribute).Namespace}, | |
{"AttribTargetAssembly", assemblyFile}, | |
{"Version", assembly.GetName().Version.ToString()}, | |
{"MajorVersion", assembly.GetName().Version.Major.ToString()}, | |
{"MinorVersion", assembly.GetName().Version.Minor.ToString()}, | |
{"BuildVersion", assembly.GetName().Version.Build.ToString()}, | |
{"RevisionVersion", assembly.GetName().Version.Revision.ToString()}, | |
}); | |
foreach (var assemblyAttribute in assemblyAttributes) | |
{ | |
var attributeResult = new Dictionary<string, string>() | |
{ | |
{"AttribTargetAssembly", assemblyFile}, | |
}; | |
attributeResult["AttribFullName"] = assemblyAttribute.Constructor.DeclaringType.FullName; | |
attributeResult["AttribName"] = assemblyAttribute.Constructor.DeclaringType.Name; | |
attributeResult["AttribNamespace"] = assemblyAttribute.Constructor.DeclaringType.Namespace; | |
output.Add(attributeResult); | |
var constructorParamNames = assemblyAttribute.Constructor.GetParameters(); | |
for (int i = 0; i < assemblyAttribute.ConstructorArguments.Count; i++) | |
{ | |
attributeResult[constructorParamNames[i].Name] = Convert.ToString(assemblyAttribute.ConstructorArguments[i].Value); | |
} | |
if (assemblyAttribute.NamedArguments != null) | |
{ | |
foreach (var namedArg in assemblyAttribute.NamedArguments) | |
{ | |
attributeResult[namedArg.MemberInfo.Name] = Convert.ToString(namedArg.TypedValue.Value); | |
} | |
} | |
} | |
} | |
finally | |
{ | |
AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve -= CurrentDomain_ReflectionOnlyAssemblyResolve; | |
} | |
return output; | |
} | |
static Assembly CurrentDomain_ReflectionOnlyAssemblyResolve(object sender, ResolveEventArgs args) | |
{ | |
try | |
{ | |
return Assembly.ReflectionOnlyLoad(args.Name); | |
} | |
catch (FileNotFoundException fileNotFoundException) | |
{ | |
try | |
{ | |
var path = Path.GetDirectoryName(args.RequestingAssembly.Location); | |
path = Path.Combine(path, args.Name); | |
return Assembly.ReflectionOnlyLoadFrom(path); | |
} | |
catch (Exception) { } | |
} | |
catch (Exception) { } | |
return null; | |
} | |
} | |
internal class AssemblyAttributeGetter : MarshalByRefObject, IAssemblyAttributeGetter | |
{ | |
public IEnumerable<IEnumerable<KeyValuePair<string, string>>> GetAssemblyAttributes(string assemblyFile) | |
{ | |
var output = new List<IDictionary<string, string>>(); | |
var assembly = Assembly.LoadFrom(assemblyFile); | |
var attribs = assembly.GetCustomAttributes(true); | |
foreach (var attrib in attribs) | |
{ | |
var dict = new Dictionary<string, string>(); | |
dict["AttribName"] = attrib.GetType().Name; | |
dict["AttribFullName"] = attrib.GetType().FullName; | |
dict["AttribNamespace"] = attrib.GetType().Namespace; | |
foreach (var prop in attrib.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public).Where(prop => prop.CanRead)) | |
{ | |
dict[prop.Name] = Convert.ToString(prop.GetValue(attrib, null)); | |
} | |
output.Add(dict); | |
} | |
return output; | |
} | |
} | |
internal class InProcessAssemblyAttributeGetter : MarshalByRefObject, IAssemblyAttributeGetter | |
{ | |
readonly IAssemblyAttributeGetter _inner; | |
public InProcessAssemblyAttributeGetter(IAssemblyAttributeGetter inner) | |
{ | |
_inner = inner; | |
} | |
public IEnumerable<IEnumerable<KeyValuePair<string, string>>> GetAssemblyAttributes(string assemblyFile) | |
{ | |
var result = _inner.GetAssemblyAttributes(assemblyFile); | |
return result; | |
} | |
} | |
internal class IsolatedAssemblyAttributeGetter : MarshalByRefObject, IAssemblyAttributeGetter | |
{ | |
static readonly string _assemblyName = Assembly.GetExecutingAssembly().FullName; | |
static readonly string _codeBase = Assembly.GetExecutingAssembly().CodeBase; | |
readonly IAssemblyAttributeGetter _inner; | |
public IsolatedAssemblyAttributeGetter(IAssemblyAttributeGetter inner) | |
{ | |
_inner = inner; | |
} | |
public IEnumerable<IEnumerable<KeyValuePair<string, string>>> GetAssemblyAttributes(string assemblyFile) | |
{ | |
//AppDomain.CurrentDomain.AssemblyResolve += NewDomainOnAssemblyResolve; | |
var newDomain = AppDomain.CreateDomain("GetAssemblyAttributes", new Evidence(AppDomain.CurrentDomain.Evidence), new AppDomainSetup() | |
{ | |
ApplicationBase = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), | |
ApplicationName = AppDomain.CurrentDomain.FriendlyName, | |
// PrivateBinPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), | |
AppDomainInitializerArguments = new[] { _codeBase }, | |
AppDomainInitializer = args => | |
{ | |
//Assembly.LoadFile(args[0]); | |
}, | |
}); | |
//newDomain.AssemblyResolve += NewDomainOnAssemblyResolve; | |
try | |
{ | |
var proxiedInner = (IAssemblyAttributeGetter)newDomain.CreateInstanceAndUnwrap(_inner.GetType().Assembly.FullName, _inner.GetType().FullName); | |
return proxiedInner.GetAssemblyAttributes(assemblyFile); | |
} | |
finally | |
{ | |
//AppDomain.CurrentDomain.AssemblyResolve -= NewDomainOnAssemblyResolve; | |
//newDomain.AssemblyResolve -= NewDomainOnAssemblyResolve; | |
AppDomain.Unload(newDomain); | |
} | |
} | |
static Assembly NewDomainOnAssemblyResolve(object sender, ResolveEventArgs args) | |
{ | |
return null; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment