如何使用IMetaDataDispenser.OpenScope才能访问嵌入式集的元数据?如何使用、嵌入式、才能、数据

由网友(命如纸薄)分享简介:我有一个.NET解决方案其中包括几个项目。这可以说,这些项目中的一个在逻辑上是一个主要的一个,其他都是次要的。我们的团队已经决定建设该项目的下一个方式。主要项目将产生的程序集(我将它称之为小学)。所有其他项目的组件都是次要的,他们将被作为资源嵌入到主之一。I have a .NET solution which co...

我有一个.NET解决方案其中包括几个项目。这可以说,这些项目中的一个在逻辑上是一个主要的一个,其他都是次要的。我们的团队已经决定建设该项目的下一个方式。主要项目将产生的程序集(我将它称之为小学)。所有其他项目的组件都是次要的,他们将被作为资源嵌入到主之一。

I have a .NET solution which consists of several projects. It's possible to say that one of these projects is logically a primary one and all others are secondary. Our team has decided to build the project the next way. The main project will produce an assembly (I'll refer it to as Primary). All other projects' assemblies are Secondary and they will be embedded as a resource into the Primary one.

来源$ C ​​$ cForExceptionHelper 类的主要项目负责获取使用上的每一个遇到的异常PDB文件的原始源$ C ​​$ C。要做到这一点我用所描述的方法的此处。它在我的独立概念的项目证明工作正常。但是,当我试图该类进入真正的解决方案,我遇到了一个问题: IMetaDataDispenser.OpenScope 方法需要非空引用汇编文件的路径。当然,我没有为任何二级组件的这种引用(因为他们的文件中嵌入的主)。出于这个原因,我不能创建类型 ISymbolReader 的对象,并读取源$ C ​​$ C。我该如何解决这个问题?顺便说一句,因为我们只嵌入辅助组件没有他们的PDB文件(虽然我们将做到这一点,如果有必要)的问题更是雪上加霜。

The SourceCodeForExceptionHelper class in the Primary project is responsible for getting the original source code using PDB files on every encountered exception. To do that I use the approach described here. It worked correctly in my separate proof of concept project. But when I tried to move that class into the real solution I've encountered a problem: the IMetaDataDispenser.OpenScope method requires not null reference to assembly file's path. Surely, I haven't such a reference for any of Secondary assembly (because their files are embedded in the Primary). For that reason I can't create an object of the type ISymbolReader and read the source code. How can I solve that problem? By the way, the problem is even worse because we embed only Secondary assemblies without their PDB files (though we will do it if it is necessary).

在此先感谢您的帮助和建议!

Thanks in advance for any help and advice!

推荐答案

我不认为你可以使用.NET Framework内置函数,因为它们依赖于物理文件做到这一点。但是,使用单塞西尔库中的解决方案,因为它有一个重载接受一个流作为输入,而不是它的符号阅读器的文件路径。

I don't think you can do this using the .NET Framework builtin functions, as they rely on physical files. However, there is a solution using the Mono Cecil library, as it has an overloads that takes a Stream as input instead of a file path for its symbols reader.

下面是一个名为TestPdb控制台应用程序,它清除其IL code到控制台,包括PDB信息的一个例子:

Here is an example of a Console app named "TestPdb" which dumps its IL code to the console, including PDB information:

using System;
using System.IO;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Cecil.Pdb;

namespace TestPdb
{
    class Program
    {
        static void Main(string[] args)
        {
            // we use a Stream for the assembly
            AssemblyDefinition asm;
            using (FileStream asmStream = new FileStream("testpdb.exe", FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                asm = AssemblyDefinition.ReadAssembly(asmStream);
            }

            // we use a Stream for the PDB
            using (FileStream symbolStream = new FileStream("testpdb.pdb", FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                asm.MainModule.ReadSymbols(new PdbReaderProvider().GetSymbolReader(asm.MainModule, symbolStream));
            }

            TypeDefinition type = asm.MainModule.GetType("TestPdb.Program");

            foreach (MethodDefinition method in type.Methods)
            {
                Console.WriteLine("Method:" + method.Name);
                foreach (Instruction ins in method.Body.Instructions)
                {
                    Console.WriteLine(" " + ins);
                    if (ins.SequencePoint != null)
                    {
                        Console.WriteLine("  Url:" + ins.SequencePoint.Document.Url);
                        // see http://blogs.msdn.com/b/jmstall/archive/2005/06/19/feefee-sequencepoints.aspx
                        if (ins.SequencePoint.StartLine != 0xFEEFEE)
                        {
                            Console.WriteLine("  StartLine:" + ins.SequencePoint.StartLine + " StartColumn:" + ins.SequencePoint.StartColumn);
                            Console.WriteLine("  EndLine:" + ins.SequencePoint.EndLine + " EndColumn:" + ins.SequencePoint.EndColumn);
                        }
                        // etc...
                    }
                }
            }   
        }
    }
}

注:因为你只需要从PDBS阅读,你可以重新编译塞西尔库定义的READ_ONLY条件符号,以节省一些字节。您还可以嵌入塞西尔源$ C ​​$直接c。在程序集,没有必要使用.dll文件的版本。

NOTE: since you only need to read from PDBs, you can recompile the Cecil library defining the READ_ONLY conditional symbol to save some bytes. You can also embed Cecil source code directly in your assemblies, no need to use the .DLL versions.

阅读全文

相关推荐

最新文章