mirror of
https://github.com/JogmansonReal/Radicade.git
synced 2026-10-25 15:09:26 -07:00
119 lines
3.5 KiB
C#
119 lines
3.5 KiB
C#
using System.Reflection.Metadata;
|
|
using System.Reflection.PortableExecutable;
|
|
using System.Text;
|
|
|
|
|
|
if (args.Length < 2)
|
|
{
|
|
Console.Error.WriteLine("Usage: InteropInspect <assembly.dll> <keyword>... | <assembly.dll> --type <FullName>");
|
|
return 1;
|
|
}
|
|
|
|
var path = args[0];
|
|
var detail = false;
|
|
string detailType = null;
|
|
var keywords = new List<string>();
|
|
for (int i = 1; i < args.Length; i++)
|
|
{
|
|
if (args[i] == "--type" && i + 1 < args.Length) { detail = true; detailType = args[++i]; }
|
|
else keywords.Add(args[i]);
|
|
}
|
|
|
|
using var fs = File.OpenRead(path);
|
|
using var pe = new PEReader(fs);
|
|
var md = pe.GetMetadataReader();
|
|
|
|
string GetString(StringHandle h) => md.GetString(h);
|
|
string GetNs(TypeDefinition t)
|
|
{
|
|
var ns = GetString(t.Namespace);
|
|
var decl = t.GetDeclaringType();
|
|
if (!decl.IsNil)
|
|
{
|
|
var outer = md.GetTypeDefinition(decl);
|
|
return GetNs(outer) + "+" + GetString(outer.Name);
|
|
}
|
|
return ns;
|
|
}
|
|
|
|
foreach (var tdh in md.TypeDefinitions)
|
|
{
|
|
var td = md.GetTypeDefinition(tdh);
|
|
var fullName = GetNs(td) + "." + GetString(td.Name);
|
|
|
|
bool match;
|
|
if (detail)
|
|
match = fullName.Equals(detailType, StringComparison.OrdinalIgnoreCase);
|
|
else
|
|
match = keywords.Any(k => fullName.IndexOf(k, StringComparison.OrdinalIgnoreCase) >= 0 ||
|
|
(k.StartsWith("field:") && td.GetFields().Any(f =>
|
|
GetString(md.GetFieldDefinition(f).Name).Contains(k[6..], StringComparison.OrdinalIgnoreCase))));
|
|
|
|
if (!match) continue;
|
|
|
|
if (!detail)
|
|
{
|
|
Console.WriteLine(fullName);
|
|
continue;
|
|
}
|
|
|
|
var sb = new StringBuilder();
|
|
sb.AppendLine($"TYPE {fullName}");
|
|
if (!td.BaseType.IsNil)
|
|
{
|
|
try { sb.AppendLine($" base: {ResolveName(md, td.BaseType)}"); } catch { }
|
|
}
|
|
foreach (var iih in td.GetInterfaceImplementations())
|
|
{
|
|
var ii = md.GetInterfaceImplementation(iih);
|
|
try { sb.AppendLine($" impl: {ResolveName(md, ii.Interface)}"); } catch { }
|
|
}
|
|
sb.AppendLine(" fields:");
|
|
foreach (var fh in td.GetFields())
|
|
{
|
|
var f = md.GetFieldDefinition(fh);
|
|
var constantHandle = f.GetDefaultValue();
|
|
var constantValue = "";
|
|
if (!constantHandle.IsNil)
|
|
{
|
|
var constant = md.GetConstant(constantHandle);
|
|
var reader = md.GetBlobReader(constant.Value);
|
|
constantValue = " = " + reader.ReadConstant(constant.TypeCode);
|
|
}
|
|
sb.AppendLine($" {GetString(f.Name)}{constantValue}");
|
|
}
|
|
sb.AppendLine(" methods:");
|
|
foreach (var mh in td.GetMethods())
|
|
{
|
|
var m = md.GetMethodDefinition(mh);
|
|
var attrs = m.Attributes;
|
|
var prms = m.GetParameters().Select(ph => md.GetParameter(ph))
|
|
.Select(pp => $"{GetString(pp.Name)}");
|
|
sb.AppendLine($" {GetString(m.Name)}({string.Join(", ", prms)}) [{attrs}]");
|
|
}
|
|
sb.AppendLine(" properties:");
|
|
foreach (var ph in td.GetProperties())
|
|
{
|
|
var p = md.GetPropertyDefinition(ph);
|
|
sb.AppendLine($" {GetString(p.Name)}");
|
|
}
|
|
Console.Write(sb.ToString());
|
|
}
|
|
|
|
return 0;
|
|
|
|
static string ResolveName(MetadataReader md, EntityHandle h)
|
|
{
|
|
if (h.Kind == HandleKind.TypeReference)
|
|
{
|
|
var tr = md.GetTypeReference((TypeReferenceHandle)h);
|
|
return $"{md.GetString(tr.Namespace)}.{md.GetString(tr.Name)}";
|
|
}
|
|
if (h.Kind == HandleKind.TypeDefinition)
|
|
{
|
|
var td2 = md.GetTypeDefinition((TypeDefinitionHandle)h);
|
|
return $"{md.GetString(td2.Namespace)}.{md.GetString(td2.Name)}";
|
|
}
|
|
return h.Kind.ToString();
|
|
}
|