如何使用 IMetaDataDispenser.OpenScope 访问嵌入式程序集的元数据?

问题描述 投票:0回答:1

我有一个由多个项目组成的 .NET 解决方案。可以说,这些项目之一在逻辑上是主要项目,而所有其他项目都是次要项目。我们的团队决定以下一步的方式构建该项目。主项目将生成一个程序集(我将其称为“主要”)。所有其他项目的程序集都是次要的,它们将作为资源嵌入到主要项目中。

Primary 项目中的

SourceCodeForExceptionHelper

 类负责在每次遇到异常时使用 PDB 文件获取原始源代码。为此,我使用
此处描述的方法。它在我单独的概念验证项目中工作正常。但是当我尝试将该类移至真正的解决方案时,我遇到了一个问题: IMetaDataDispenser.OpenScope
 方法要求对程序集文件路径的非空引用。当然,我没有任何辅助程序集的此类参考(因为它们的文件嵌入在主程序集中)。因此,我无法创建 
ISymbolReader
 类型的对象并读取源代码。我该如何解决这个问题?顺便说一句,问题更严重,因为我们只嵌入辅助程序集而没有 PDB 文件(尽管如果有必要我们会这样做)。

预先感谢您的任何帮助和建议!

c# .net debugging pdb-files
1个回答
3
投票
我认为您无法使用 .NET Framework 内置函数来执行此操作,因为它们依赖于物理文件。然而,有一个使用

Mono Cecil 库的解决方案,因为它有一个重载,将 Stream 作为输入而不是其符号读取器的文件路径。

这是一个名为“TestPdb”的控制台应用程序的示例,它将其 IL 代码转储到控制台,包括 PDB 信息:

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... } } } } } }

注意:由于您只需要从 PDB 中读取,因此您可以重新编译 Cecil 库并定义 READ_ONLY 条件符号以节省一些字节。您还可以将 Cecil 源代码直接嵌入到程序集中,无需使用 .DLL 版本。

© www.soinside.com 2019 - 2024. All rights reserved.