首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ILSpy,如何解析依赖关系?

ILSpy,如何解析依赖关系?
EN

Stack Overflow用户
提问于 2012-01-01 01:28:56
回答 4查看 7.1K关注 0票数 6

我想用ILSpy反汇编整个.NET程序集。

我使用以下代码作为基础:

http://skysigal.xact-solutions.com/Blog/tabid/427/entryid/2488/Default.aspx

它工作得很好,只是当我有一个引用Npgsql.dll的程序集(或任何其他非gac程序集)时,我就会得到一个AssemblyResolutionException。

无法解析程序集:'Npgsql,Version=2.0.11.92,Culture=neutral,PublicKeyToken=5d8b90d52f46fda7‘

我知道如何获取引用的程序集,但如何将它们添加到ast?

代码语言:javascript
复制
    // SqlWebAdmin.Models.Decompiler.DecompileAssembly("xy.dll");
    public static string DecompileAssembly(string pathToAssembly)
    {
        //Assembly assembly = Assembly.LoadFrom(pathToAssembly);
        System.Reflection.Assembly assembly = System.Reflection.Assembly.ReflectionOnlyLoadFrom(pathToAssembly);
        //assembly.GetReferencedAssemblies();

        //assembly.GetReferencedAssemblies(assembly);
        Mono.Cecil.AssemblyDefinition assemblyDefinition =
            Mono.Cecil.AssemblyDefinition.ReadAssembly(pathToAssembly);



        ICSharpCode.Decompiler.Ast.AstBuilder astBuilder = new ICSharpCode.Decompiler.Ast.AstBuilder(new ICSharpCode.Decompiler.DecompilerContext(assemblyDefinition.MainModule));
        astBuilder.AddAssembly(assemblyDefinition);


        //new Helpers.RemoveCompilerAttribute().Run(decompiler.CompilationUnit);
        using (System.IO.StringWriter output = new System.IO.StringWriter())
        {
            astBuilder.GenerateCode(new ICSharpCode.Decompiler.PlainTextOutput(output));
            string result = output.ToString();
            return result;
        }

        return "";
    } // End Function DecompileAssembly
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-01-03 02:20:54

您需要告诉ILSpy正在使用的底层元数据读取器Cecil,您的程序集在哪里。你可以这样写:

代码语言:javascript
复制
var resolver = new DefaultAssemblyResolver();
resolver.AddSearchDirectory("path/to/my/assemblies");

var parameters = new ReaderParameters
{
    AssemblyResolver = resolver,
};

var assembly = AssemblyDefinition.ReadAssembly(pathToAssembly, parameters);

这是告诉Cecil在哪里解析引用的程序集的最自然的方式。这样,您可以删除使用System.Reflection加载程序集的行,并且只使用ILSpy堆栈。

票数 14
EN

Stack Overflow用户

发布于 2016-01-29 17:31:41

这是经过改进的@Nayan回答。如果要忽略缺少的程序集,请复制此类:

代码语言:javascript
复制
using Mono.Cecil;

public class IgnoringExceptionsAssemblyResolver : DefaultAssemblyResolver
{
    public override AssemblyDefinition Resolve(AssemblyNameReference name)
    {
        try
        {
            return base.Resolve(name);
        }
        catch
        {
            return null;
        }
    }
}

并像这样使用它:

代码语言:javascript
复制
var assembly = AssemblyDefinition.ReadAssembly(path, new ReaderParameters() {
    AssemblyResolver = new IgnoringExceptionsAssemblyResolver()
});
票数 4
EN

Stack Overflow用户

发布于 2013-08-06 20:33:34

除了JB Evain的建议之外,此代码还将帮助避免异常。你所要做的就是在解决程序中处理异常。

我承认,这不是最好的方法。但它适用于这个场景:"If I am decompiling a DLL on a system where the referred assemblies are not present, the decompilation fails (with exception.) At least, i would like to see the decompile code, for whatever has been resolved."

代码语言:javascript
复制
using System;
using System.Collections.Generic;
using Mono.Cecil;

public class MyAssemblyResolver : BaseAssemblyResolver
{
    private readonly IDictionary<string, AssemblyDefinition> cache;
    public MyAssemblyResolver()
    {
        this.cache = new Dictionary<string, AssemblyDefinition>(StringComparer.Ordinal);
    }
    public override AssemblyDefinition Resolve(AssemblyNameReference name)
    {
        if (name == null)
            throw new ArgumentNullException("name");
        AssemblyDefinition assemblyDefinition = null;
        if (this.cache.TryGetValue(name.FullName, out assemblyDefinition))
            return assemblyDefinition;
        try  //< -------- My addition to the code.
        {
            assemblyDefinition = base.Resolve(name);
            this.cache[name.FullName] = assemblyDefinition;
        }
        catch { } //< -------- My addition to the code.
        return assemblyDefinition;
    }
    protected void RegisterAssembly(AssemblyDefinition assembly)
    {
        if (assembly == null)
            throw new ArgumentNullException("assembly");
        string fullName = assembly.Name.FullName;
        if (this.cache.ContainsKey(fullName))
            return;
        this.cache[fullName] = assembly;
    }
}

并像这样使用它:

代码语言:javascript
复制
var rp = new Mono.Cecil.ReaderParameters() { AssemblyResolver = new MyAssemblyResolver() };
var assemblyDefinition = Mono.Cecil.AssemblyDefinition.ReadAssembly(assemblyStream, rp);
var astBuilder = new ICSharpCode.Decompiler.Ast.AstBuilder(
     new ICSharpCode.Decompiler.DecompilerContext(assemblyDefinition.MainModule));
astBuilder.AddAssembly(assemblyDefinition);

实际上,我希望看到反编译器中的一个增强:它目前忽略了DefaultAssemblyResolver类中用户设置的ReaderParameters

用法:

代码语言:javascript
复制
var rp = new Mono.Cecil.ReaderParameters();
var assemblyDefinition = Mono.Cecil.AssemblyDefinition.ReadAssembly(assemblyStream, rp);

当前DefaultAssemblyResolver代码:

代码语言:javascript
复制
public override AssemblyDefinition Resolve(AssemblyNameReference name)
{
    if (name == null)
    {
        throw new ArgumentNullException("name");
    }
    AssemblyDefinition assemblyDefinition;
    if (this.cache.TryGetValue(name.FullName, out assemblyDefinition))
    {
        return assemblyDefinition;
    }
    assemblyDefinition = base.Resolve(name); // <---------
// Is the `ReaderParameters` object set by user, used to resolve in `base` class?

    this.cache[name.FullName] = assemblyDefinition;
    return assemblyDefinition;
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8689505

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档