【问题标题】:List classes and function headers from a C# DLL列出 C# DLL 中的类和函数头
【发布时间】:2023-04-06 11:10:01
【问题描述】:

我有一个第三方 C# DLL(经过混淆处理),我想使用 pythonnet 将它包装在 python 中。

到目前为止,我可以通过在 Visual Studio 2017 中检查 DLL 内容并逐个函数手动编写包装函数来做我想做的事,而且有数百个。我看不到在文本文件中列出或将我在 VS dll 资源管理器中看到的内容复制到文本文件以自动化包装任务的方法。

有没有办法将 .NET (C#) DLL 文件的内容列成文本?

【问题讨论】:

  • 使用ildasm /tokens /pubonly /out=dll.txt pathToDll.dll
  • 命令说:“受保护的模块:无法反汇编”,我不关心标题的内容。

标签: c# python dll


【解决方案1】:

你可以试试这个。

使用反射和 CodeDom,此实现尝试为给定程序集中的所有类型、它们的属性和它们的方法生成空主体源代码。

只需传递PrintOutAssembly 对混淆库程序集的引用即可。

希望这会有所帮助。

private static void PrintOutMethod(CodeTypeDeclaration codeTypeDeclaration, MethodInfo method)
{
    if (method.Name.StartsWith("get_") || method.Name.StartsWith("set_"))
    {
        return;
    }

    CodeMemberMethod codeMethod;

    codeTypeDeclaration.Members.Add
    (
        codeMethod = new CodeMemberMethod()
        {
            Name = method.Name,
            ReturnType = new CodeTypeReference(method.ReturnType),
            Attributes =
                (MemberAttributes.Public) |
                (method.IsFinal ? MemberAttributes.Final : MemberAttributes.Public) |
                (method.IsAbstract ? MemberAttributes.Abstract : MemberAttributes.Public) |
                (method.GetBaseDefinition() != null ? MemberAttributes.Override : MemberAttributes.Public)
        }
    );

    foreach (ParameterInfo parameter in method.GetParameters())
    {
        codeMethod.Parameters.Add
        (
            new CodeParameterDeclarationExpression()
            {
                Name = parameter.Name,
                Direction = parameter.IsIn && parameter.IsOut ? FieldDirection.Ref : parameter.IsOut ? FieldDirection.Out : FieldDirection.In,
                Type = new CodeTypeReference(parameter.ParameterType)
            }
        );
    }
}

private static void PrintOutProperty(CodeTypeDeclaration codeTypeDeclaration, PropertyInfo property)
{
    codeTypeDeclaration.Members.Add
    (
        new CodeMemberProperty()
        {
            Name = property.Name,
            Type = new CodeTypeReference(property.PropertyType),
            HasGet = property.GetMethod != null,
            HasSet = property.SetMethod != null,
            Attributes =
                (MemberAttributes.Public) |
                (property.GetMethod != null && property.GetMethod.IsFinal ? MemberAttributes.Final : MemberAttributes.Public) |
                (property.SetMethod != null && property.GetMethod.IsFinal ? MemberAttributes.Final : MemberAttributes.Public) |
                (property.GetMethod != null && property.GetMethod.IsAbstract ? MemberAttributes.Abstract : MemberAttributes.Public) |
                (property.SetMethod != null && property.GetMethod.IsAbstract ? MemberAttributes.Abstract : MemberAttributes.Public)
        }
    );
}

static Dictionary<string, CodeNamespace> namespaces = new Dictionary<string, CodeNamespace>();

private static void PrintOutType(System.CodeDom.CodeCompileUnit metaAssembly, CodeTypeDeclaration parentCodeTypeDeclaration, Type type)
{
    CodeNamespace codeNamespace;
    if (!namespaces.ContainsKey(type.Namespace))
    {
        namespaces[type.Namespace] = codeNamespace = new CodeNamespace(type.Namespace);
        metaAssembly.Namespaces.Add(codeNamespace);
    }
    else
    {
        codeNamespace = namespaces[type.Namespace];
    }

    CodeTypeDeclaration codeTypeDeclaration = new CodeTypeDeclaration(type.Name)
    {
        IsClass = type.IsClass,
        IsEnum = type.IsEnum,
        IsInterface = type.IsInterface,
        IsPartial = false,
        IsStruct = type.IsValueType && !type.IsEnum,
        Attributes = MemberAttributes.Public |
            (type.IsAbstract ? MemberAttributes.Abstract : MemberAttributes.Public) |
            (type.IsSealed ? MemberAttributes.Final : MemberAttributes.Public)
    };

    if (type.BaseType != null && type.BaseType != typeof(object))
    {
        codeTypeDeclaration.BaseTypes.Add(type.BaseType);
    }

    foreach (Type interfaceType in type.GetInterfaces())
    {
        codeTypeDeclaration.BaseTypes.Add(interfaceType);
    }

    if (parentCodeTypeDeclaration == null)
    {
        codeNamespace.Types.Add(codeTypeDeclaration);
    }
    else
    {
        parentCodeTypeDeclaration.Members.Add(codeTypeDeclaration);
    }

    foreach (Type nestedType in type.GetNestedTypes())
    {
        if (nestedType.IsPublic)
        {
            PrintOutType(metaAssembly, codeTypeDeclaration, nestedType);
        }
    }

    foreach (PropertyInfo publicProperty in type.GetProperties(BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance))
    {
        PrintOutProperty(codeTypeDeclaration, publicProperty);
    }

    foreach (MethodInfo publicMethod in type.GetMethods(BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance))
    {
        PrintOutMethod(codeTypeDeclaration, publicMethod);
    }
}

private static void PrintOutAssembly(Assembly assembly)
{
    Console.WriteLine("// Meta generation for assembly: {0}", assembly.FullName);

    System.CodeDom.CodeCompileUnit metaAssembly = new System.CodeDom.CodeCompileUnit();

    foreach (Type exportedType in assembly.GetExportedTypes())
    {
        PrintOutType(metaAssembly, null, exportedType);
    }

    System.CodeDom.Compiler.CodeDomProvider.CreateProvider("C#").GenerateCodeFromCompileUnit
    (
        metaAssembly,
        new StreamWriter(Console.OpenStandardOutput()),
        new System.CodeDom.Compiler.CodeGeneratorOptions() { BlankLinesBetweenMembers = true, IndentString = "    ", BracingStyle = "C" }
    );
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-16
    • 1970-01-01
    相关资源
    最近更新 更多