I use the roslyn compiler to compile code on demand.
Now when there is an Exception in the compiled code (example: Divided by Zero Exception) I get in Visual Studio the line number displayed:

But when I do stacktrace.ToString() the line information is not included. In frame.GetLineNumber the line number is also 0.
The code for handling the exception:
    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());
     }
The Code for Compiling my Code on demand
 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;
        }
     }
Picture for provided Solution Suggestion:

UPDATE: As per Hans Passant comment:
If you are running in .NET Core you'll need PortablePDB files; for .NET Framework you'll need PDB files
According to MSDN StackTrace.GetFrame(0) returns the most recent function call, which would be IEnumerator<T>.MoveNext() and you need the PDB file for .NET Framework or PortablePDB for .NET Core for that function (but you don't have it).
You should iterate over the StackFrames from 0 to StackTrace.FrameCount - 1, stopping at the first StackFrame.GetFileLineNumber() > 0:
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());
This correctly prints
Exception message: Sequence contains no elements
Exception in file: [FilePath]\Root.cs
Exception in method: System.Object GetModuleDescription(System.Object[])
Exception at line number: 70
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With