1

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

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

提前感谢您的任何帮助和建议!

4

1 回答 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 中读取,您可以重新编译定义 READ_ONLY 条件符号的 Cecil 库以节省一些字节。您还可以将 Cecil 源代码直接嵌入到您的程序集中,无需使用 .DLL 版本。

于 2011-09-30T10:06:19.403 回答