Advertisement
Guest User

Untitled

a guest
Jun 17th, 2019
58
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.25 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using CecilTool;
  5. using Mono.Cecil;
  6.  
  7. namespace CecilTool
  8. {
  9. /// <summary>
  10. /// Simple tool using Mono.Cecil to dump the list of usage of internals methods/fields
  11. /// referencing another assembly from a specified assembly.
  12. ///
  13. /// Usage: ApiVerifier.DumpUsageOfInternalsFromExternalAssemblies(@"C:\Path\To\My\Assembly.dll")
  14. ///
  15. /// </summary>
  16. public static class ApiVerifier
  17. {
  18. public static void DumpUsageOfInternalsFromExternalAssemblies(string assemblyPath)
  19. {
  20. if (assemblyPath == null) throw new ArgumentNullException(nameof(assemblyPath));
  21. DumpUsageOfInternalsFromExternalAssemblies(new List<string>() {assemblyPath});
  22. }
  23.  
  24. public static void DumpUsageOfInternalsFromExternalAssemblies(List<string> assemblyPaths)
  25. {
  26. if (assemblyPaths == null) throw new ArgumentNullException(nameof(assemblyPaths));
  27. var assemblyFullPaths = new List<string>();
  28. var assemblyResolver = new DefaultAssemblyResolver();
  29. foreach (var assemblyPath in assemblyPaths)
  30. {
  31. var fullPath = Path.Combine(Environment.CurrentDirectory, assemblyPath);
  32. assemblyFullPaths.Add(fullPath);
  33. assemblyResolver.AddSearchDirectory(Path.GetDirectoryName(fullPath));
  34. }
  35.  
  36. for (var i = 0; i < assemblyFullPaths.Count; i++)
  37. {
  38. var fullPath = assemblyFullPaths[i];
  39. var assembly = AssemblyDefinition.ReadAssembly(fullPath, new ReaderParameters(ReadingMode.Immediate)
  40. {
  41. AssemblyResolver = assemblyResolver
  42. });
  43. if (i > 0) Console.WriteLine();
  44. DumpUsageOfInternalsFromExternalAssemblies(assembly);
  45. }
  46. }
  47.  
  48. public static void DumpUsageOfInternalsFromExternalAssemblies(AssemblyDefinition assembly)
  49. {
  50. if (assembly == null) throw new ArgumentNullException(nameof(assembly));
  51. const int mdCountMax = 1 << 24;
  52. bool dumpAssemblyName = true;
  53. foreach (var module in assembly.Modules)
  54. {
  55. for (int i = 1; i < mdCountMax; i++)
  56. {
  57. var item = module.LookupToken(new MetadataToken(TokenType.MemberRef, i));
  58. if (item == null)
  59. {
  60. break;
  61. }
  62.  
  63. if (item is MemberReference memberRef)
  64. {
  65. var memberDef = memberRef.Resolve();
  66. bool isInternal = CheckIsInternal(memberDef);
  67. if (isInternal && !assembly.Modules.Contains(memberDef.DeclaringType.Module))
  68. {
  69. if (dumpAssemblyName)
  70. {
  71. Console.WriteLine($"Internals used in Assembly: {assembly.Name} ({assembly.MainModule.FileName})");
  72. Console.WriteLine("---------------------------------------------------------------------------------------");
  73. dumpAssemblyName = false;
  74. }
  75.  
  76. Console.WriteLine($"{memberDef.GetType().Name}: {memberRef} => Assembly: {memberDef.DeclaringType.Module.FileName}");
  77. }
  78. }
  79. }
  80. }
  81. }
  82. private static bool CheckIsInternal(IMemberDefinition memberDef)
  83. {
  84. if (memberDef == null)
  85. {
  86. return false;
  87. }
  88.  
  89. bool isInternal = false;
  90. switch (memberDef)
  91. {
  92. case MethodDefinition methodDef:
  93. isInternal = methodDef.IsAssembly;
  94. break;
  95. case FieldDefinition fieldDef:
  96. isInternal = fieldDef.IsAssembly;
  97. break;
  98. case TypeDefinition typeDef:
  99. isInternal = !(typeDef.IsPublic || typeDef.IsNestedPublic);
  100. break;
  101. }
  102.  
  103. // Check also the declaring type
  104. return isInternal || CheckIsInternal(memberDef.DeclaringType);
  105. }
  106. }
  107. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement