首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >异常堆栈跟踪中不包括行号(用Roslyn动态编译代码)

异常堆栈跟踪中不包括行号(用Roslyn动态编译代码)
EN

Stack Overflow用户
提问于 2019-12-09 09:56:55
回答 2查看 1.9K关注 0票数 4

我使用roslyn编译器按需编译代码。

现在,当编译的代码(例如:除以零异常)中出现异常时,我在Visual中得到了显示的行号:

但是,当我执行stacktrace.ToString()时,行信息不包括在内。在frame.GetLineNumber中,行号也是0。

处理异常的代码:

代码语言:javascript
复制
    try
     {
        int i = 0;
        int iiii = 5 / i; 
     }
     catch (Exception ex)
     {
        var stackTrace = new StackTrace(ex, true);
        var frame = stackTrace.GetFrame(0);

        Console.WriteLine("Exception message: {0}", ex.Message);
        Console.WriteLine("Exception in file: {0}", frame.GetFileName());
        Console.WriteLine("Exception in method: {0}", frame.GetMethod());
        Console.WriteLine("Exception at line numer: {0}", frame.GetFileLineNumber());
     }

按需编写我的代码代码

代码语言:javascript
复制
 CSharpParseOptions po = new CSharpParseOptions(LanguageVersion.CSharp7, DocumentationMode.Parse, SourceCodeKind.Regular);
     SyntaxTree parsedSyntaxTree = SyntaxFactory.ParseSyntaxTree(code, po);

     List<string> defaultNamespaces = GetUsings(parsedSyntaxTree);

     //// Referenzen über Kommentare heraussuchen:
     List<MetadataReference> defaultReferences = GetReferences(parsedSyntaxTree, rootPfad);

     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);


     CSharpCompilationOptions defaultCompilationOptions =
           new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
                   .WithOverflowChecks(true).WithOptimizationLevel(OptimizationLevel.Debug).WithPlatform(Platform.AnyCpu)
                   .WithUsings(defaultNamespaces);

     CSharpCompilation compilation = CSharpCompilation.Create(
         assemblyName,
         syntaxTrees: new[] { encoded },
         references: defaultReferences,

         options: defaultCompilationOptions
     );

     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)
        {
           Console.WriteLine("Kompilierung erfolgreich!");
           try
           {
              var assembly = Assembly.Load(assemblyStream.ToArray(), symbolsStream.ToArray());
              var parsedCodeInfo = new IM3ParsedCodeInfo() { Assembly = assembly, Erfolgreich = true };

              return parsedCodeInfo;
           }
           catch (Exception ex)
           {
              Console.WriteLine("Ausnahme aufgetreten:");
              Console.WriteLine(ex);

              var parsedCodeInfo = new IM3ParsedCodeInfo() { ErrorException = ex, Erfolgreich = false };
              return parsedCodeInfo;
           }
        }
        else
        {
           Console.WriteLine("Kompilierung nicht erfolgreich!");
           foreach (var diagnostic in result.Diagnostics)
           {
              Console.WriteLine(diagnostic.ToString());
           }

           var parsedCodeInfo = new IM3ParsedCodeInfo() { ErrorDiagnostics = result.Diagnostics, Erfolgreich = false };
           return parsedCodeInfo;
        }
     }

提供的解决方案建议的图片:

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-12-12 01:06:04

更新: As Hans 注释:

如果在.NET Core中运行,则需要PortablePDB文件;对于.NET Framework,则需要PDB文件

根据MSDNStackTrace.GetFrame(0)返回最近的函数调用,它将是IEnumerator<T>.MoveNext(),您需要用于.NET框架的PDB文件或用于该函数的.NET核心的PortablePDB (但您没有)。

您应该将StackFrames0循环到StackTrace.FrameCount - 1,在第一个StackFrame.GetFileLineNumber() > 0处停止。

代码语言:javascript
复制
var stack = new StackFrame(ex, true);
StackFrame frame = null;
for (int i = 0; i < stack.FrameCount; i++)
{
    frame = stack.GetFrame(i);
    if (frame.GetFileLineNumber() > 0) break;
}

Console.WriteLine("Exception message: {0}", ex.Message);
Console.WriteLine("Exception in file: {0}", frame.GetFileName());
Console.WriteLine("Exception in method: {0}", frame.GetMethod());
Console.WriteLine("Exception at line number: {0}", frame.GetFileLineNumber());

这个正确的打印

异常消息:序列不包含任何元素 文件中的异常: FilePath\Root.cs 方法中的异常: System.Object GetModuleDescription(System.Object[]) 行号处的例外情况: 70

票数 2
EN

Stack Overflow用户

发布于 2019-12-12 10:54:37

您还必须在脚本选项中提供源文件。

在我的例子中,看起来是这样的:

代码语言:javascript
复制
var options = ScriptOptions.Default
                           .WithReferences(references)
                           .WithFilePath(sourceFile)
                           .WithFileEncoding(sourceFileEncoding)
                           .WithEmitDebugInformation(true)
                           .WithImports(imports);

注意WithFilePath(sourceFile)

在我的例子中,我将使用它来创建脚本:

代码语言:javascript
复制
CSharpScript.Create(this.Content, options, globalType);

为了得到大会:

代码语言:javascript
复制
script.Compile();
var stream = new MemoryStream();
using (stream)
{
  var emitResult = script.GetCompilation().Emit(stream);

  if (emitResult.Success)
    return Assembly.Load(stream.ToArray());
}

我刚查过了,它在堆栈跟踪中显示了行号。如果你需要更多的信息,只需回复。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59246357

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档