【问题标题】:How to debug dll generated from Roslyn compilation?如何调试从 Roslyn 编译生成的 dll?
【发布时间】:2018-11-11 23:19:22
【问题描述】:

我正在使用 Roslyn CSharpCompilation 为我的插件生成 dll 文件 - 文件包含 OptimizationLevel.Debug 并生成 pdb 文件。接下来,我使用 Assembly.Load 将这些文件加载​​到我的程序(UWP + .NET Standard 2.0 库)并创建我感兴趣的类型的实例。我的问题是我无法获得 Visual Studio(版本 2017 15.7. 3)在调试时查找源代码 - 它像外部库一样踩它,所以当内部抛出异常时我找不到在哪里。我已经厌倦了在 stackoverflow 上搜索解决方案,但所有解决方案都不起作用。我已经检查过了:

  • 生成pdb
  • VS 中的模块窗口显示符号已加载
  • 尝试了不同版本的程序集 Load/LoadFrom
  • 设置“使用 调试选项中的“托管兼容模式”

有什么方法可以使文件可调试?也许我必须在 VS 中编译或更改某些内容时使用一些 roslyn 选项?

【问题讨论】:

  • 你有办法解决这个问题吗?
  • 否 - 我使用的是在调试时添加到解决方案中的编译版本;(

标签: c# debugging visual-studio-2017 roslyn


【解决方案1】:

下面的代码示例应该对您有所帮助。它基于 thlamare IOC 容器 的代码生成部分,是 Jeremy D Miller 制作的 StructureMap 的继承者。

我只添加了调试功能。诀窍是使源文本可嵌入,选择正确的格式,并在需要的地方设置编码值。

查看原始作品以获取更多详细信息,例如添加引用。

public Assembly CreateAssembly(string code)
{
    var encoding = Encoding.UTF8;

    var assemblyName = Path.GetRandomFileName();
    var symbolsName = Path.ChangeExtension(assemblyName, "pdb");
    var sourceCodePath = "generated.cs";

    var buffer = encoding.GetBytes(code);
    var sourceText = SourceText.From(buffer, buffer.Length, encoding, canBeEmbedded: true);

    var syntaxTree = CSharpSyntaxTree.ParseText(
        sourceText, 
        new CSharpParseOptions(), 
        path: sourceCodePath);

    var syntaxRootNode = syntaxTree.GetRoot() as CSharpSyntaxNode;
    var encoded = CSharpSyntaxTree.Create(syntaxRootNode, null, sourceCodePath, encoding);

    var optimizationLevel = OptimizationLevel.Debug;

    CSharpCompilation compilation = CSharpCompilation.Create(
        assemblyName,
        syntaxTrees: new[] { encoded },
        references: references,
        options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
            .WithOptimizationLevel(optimizationLevel)
            .WithPlatform(Platform.AnyCpu)
    );

    using (var assemblyStream = new MemoryStream())
    using (var symbolsStream = new MemoryStream())
    {
        var emitOptions = new EmitOptions(
                debugInformationFormat: DebugInformationFormat.PortablePdb,
                pdbFilePath: symbolsName);

        var embeddedTexts = new List<EmbeddedText>
        {
            EmbeddedText.FromSource(sourceCodePath, sourceText),
        };

        EmitResult result = compilation.Emit(
            peStream: assemblyStream,
            pdbStream: symbolsStream,
            embeddedTexts: embeddedTexts,
            options: emitOptions);

        if (!result.Success)
        {
            var errors = new List<string>();

            IEnumerable<Diagnostic> failures = result.Diagnostics.Where(diagnostic =>
                diagnostic.IsWarningAsError ||
                diagnostic.Severity == DiagnosticSeverity.Error);

            foreach (Diagnostic diagnostic in failures)
                errors.Add($"{diagnostic.Id}: {diagnostic.GetMessage()}");

            throw new Exception(String.Join("\n", errors));
        }

        Console.WriteLine(code);

        assemblyStream.Seek(0, SeekOrigin.Begin);
        symbolsStream?.Seek(0, SeekOrigin.Begin);

        var assembly = AssemblyLoadContext.Default.LoadFromStream(assemblyStream, symbolsStream);
        return assembly;
    }
}

用法:

[Test]
public void Verify()
{
    var code =
        @"namespace Debuggable
        {
            public class HelloWorld
            {
                public string Greet(string name)
                {
                    var result = ""Hello, "" + name;
                    return result;
                }
            }
        }
        ";

    var codeGenerator = new CodeGenerator();
    var assembly = codeGenerator.CreateAssembly(code);

    dynamic instance = assembly.CreateInstance("Debuggable.HelloWorld");

    // Set breakpoint here
    string result = instance.Greet("Roslyn");

    result.Should().Be("Hello, Roslyn");
}

【讨论】:

  • 太好了,我可以在 Visual Studio 的调试模式 F5 下从我的脚本进行调试。但是我可以利用这种技术来创建运行时调试吗?我想与我自己的观察变量进行交互,我的编辑器会显示一个红色的错误突出显示。有可能吗?
  • 这是一种非常不舒服的方式。 (
猜你喜欢
  • 2016-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多