Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.IO;
- using CecilTool;
- using Mono.Cecil;
- namespace CecilTool
- {
- /// <summary>
- /// Simple tool using Mono.Cecil to dump the list of usage of internals methods/fields
- /// referencing another assembly from a specified assembly.
- ///
- /// Usage: ApiVerifier.DumpUsageOfInternalsFromExternalAssemblies(@"C:\Path\To\My\Assembly.dll")
- ///
- /// </summary>
- public static class ApiVerifier
- {
- public static void DumpUsageOfInternalsFromExternalAssemblies(string assemblyPath)
- {
- if (assemblyPath == null) throw new ArgumentNullException(nameof(assemblyPath));
- DumpUsageOfInternalsFromExternalAssemblies(new List<string>() {assemblyPath});
- }
- public static void DumpUsageOfInternalsFromExternalAssemblies(List<string> assemblyPaths)
- {
- if (assemblyPaths == null) throw new ArgumentNullException(nameof(assemblyPaths));
- var assemblyFullPaths = new List<string>();
- var assemblyResolver = new DefaultAssemblyResolver();
- foreach (var assemblyPath in assemblyPaths)
- {
- var fullPath = Path.Combine(Environment.CurrentDirectory, assemblyPath);
- assemblyFullPaths.Add(fullPath);
- assemblyResolver.AddSearchDirectory(Path.GetDirectoryName(fullPath));
- }
- for (var i = 0; i < assemblyFullPaths.Count; i++)
- {
- var fullPath = assemblyFullPaths[i];
- var assembly = AssemblyDefinition.ReadAssembly(fullPath, new ReaderParameters(ReadingMode.Immediate)
- {
- AssemblyResolver = assemblyResolver
- });
- if (i > 0) Console.WriteLine();
- DumpUsageOfInternalsFromExternalAssemblies(assembly);
- }
- }
- public static void DumpUsageOfInternalsFromExternalAssemblies(AssemblyDefinition assembly)
- {
- if (assembly == null) throw new ArgumentNullException(nameof(assembly));
- const int mdCountMax = 1 << 24;
- bool dumpAssemblyName = true;
- foreach (var module in assembly.Modules)
- {
- for (int i = 1; i < mdCountMax; i++)
- {
- var item = module.LookupToken(new MetadataToken(TokenType.MemberRef, i));
- if (item == null)
- {
- break;
- }
- if (item is MemberReference memberRef)
- {
- var memberDef = memberRef.Resolve();
- bool isInternal = CheckIsInternal(memberDef);
- if (isInternal && !assembly.Modules.Contains(memberDef.DeclaringType.Module))
- {
- if (dumpAssemblyName)
- {
- Console.WriteLine($"Internals used in Assembly: {assembly.Name} ({assembly.MainModule.FileName})");
- Console.WriteLine("---------------------------------------------------------------------------------------");
- dumpAssemblyName = false;
- }
- Console.WriteLine($"{memberDef.GetType().Name}: {memberRef} => Assembly: {memberDef.DeclaringType.Module.FileName}");
- }
- }
- }
- }
- }
- private static bool CheckIsInternal(IMemberDefinition memberDef)
- {
- if (memberDef == null)
- {
- return false;
- }
- bool isInternal = false;
- switch (memberDef)
- {
- case MethodDefinition methodDef:
- isInternal = methodDef.IsAssembly;
- break;
- case FieldDefinition fieldDef:
- isInternal = fieldDef.IsAssembly;
- break;
- case TypeDefinition typeDef:
- isInternal = !(typeDef.IsPublic || typeDef.IsNestedPublic);
- break;
- }
- // Check also the declaring type
- return isInternal || CheckIsInternal(memberDef.DeclaringType);
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement