我有一个.NET解决方案,它包含多个项目。可以说这些项目中的一个在逻辑上是主要的,而所有其他项目都是次要的。我们的团队决定以下一个方式构建项目。主项目将生成一个程序集(我将其称为主程序集)。所有其他项目的程序集都是辅助程序,它们将作为资源嵌入到主程序集中。
Primary项目中的SourceCodeForExceptionHelper
类负责在每个遇到的异常上使用PDB文件获取原始源代码。为此,我使用了here描述的方法。它在我单独的概念验证项目中正常工作。但是当我尝试将该类移动到真正的解决方案中时,我遇到了一个问题:IMetaDataDispenser.OpenScope
方法不需要对程序集文件的路径进行空引用。当然,我没有任何辅助程序集的引用(因为它们的文件嵌入在主程序中)。因此,我无法创建ISymbolReader
类型的对象并阅读源代码。我该如何解决这个问题?顺便说一句,问题更严重,因为我们只嵌入没有PDB文件的辅助程序集(尽管如果有必要我们会这样做)。
提前感谢您的任何帮助和建议!
答案 0 :(得分: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读取,因此可以重新编译定义READ_ONLY条件符号的Cecil库以节省一些字节。您还可以直接在程序集中嵌入Cecil源代码,无需使用.DLL版本。