2016-04-30 7 views
1

Ich füge Scripting-Möglichkeit zu meiner App hinzu. Init-Methode lädt das Skript, kompiliert es und ruft Skripts Init-Methode auf. Ich möchte in der Lage sein, Visual Studio-Debugger an meine App anzuhängen und Breakpoints in der üblichen Weise in der IDE im Skript hinzuzufügen.Laden von Symbolen für dynamisch kompilierte Assemblies

Visual Studio sagt: Loaded 'i0uu5bcn.vhy'. Die PDB-Datei kann nicht gefunden oder geöffnet werden.

Die Haltepunkte funktionieren wie folgt: System.Diagnostics.Debugger.Break();

public static string[] Init(string scriptPath, params object[] parameters) 
     { 
      List<string> errors = new List<string>(); 

      SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(File.ReadAllText(scriptPath), null, scriptPath); 

      SyntaxTree encoded = CSharpSyntaxTree.Create(syntaxTree.GetRoot() as CSharpSyntaxNode, null, scriptPath, System.Text.Encoding.UTF8); 

      string assemblyName = Path.GetRandomFileName(); 

      MetadataReference[] references = new MetadataReference[] 
      { 
       MetadataReference.CreateFromFile(typeof(object).Assembly.Location), 
       MetadataReference.CreateFromFile(typeof(Enumerable).Assembly.Location) 
      }; 

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

      Assembly finalAssembly = null; 

      using (var symbols = new MemoryStream()) 
      { 
       using (var ms = new MemoryStream()) 
       { 
        EmitResult result = compilation.Emit(ms, symbols); 

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

         foreach (Diagnostic diagnostic in failures) 
         { 
          errors.Add($"{diagnostic.Id}: {diagnostic.GetMessage()}"); 
         } 
        } 
        else 
        { 
         ms.Seek(0, SeekOrigin.Begin); 
         symbols.Seek(0, SeekOrigin.Begin); 

         finalAssembly = Assembly.Load(ms.ToArray(), symbols.ToArray()); 

         Type type = finalAssembly.DefinedTypes.First().AsType(); 
         object obj = Activator.CreateInstance(type); 
         type.InvokeMember("Init", 
          BindingFlags.Default | BindingFlags.InvokeMethod, 
          null, 
          obj, 
          parameters); 
        } 
       } 
      } 

      return errors.ToArray(); 
     } 

Antwort

2

Stellen Sie sicher, dass die Datei tatsächlich UTF8-codiert ist. Die Codierung wird verwendet, um die Eingabebytes für die Hash-Funktion zu erhalten, die beim Erzeugen der PDB verwendet wird. Beachten Sie, dass Encoding.UTF8 davon ausgeht, dass die Datei BOM hat.

Sie können die Prüfsummen aus dem erzeugten PDB-Dump (auf der Festplatte speichern erste ...) mit SourceLink:

sourcelink checksums -p <pdbfile> 

Sie können im Dump gegen einen Hash Ihres den Wert für die Skriptdatei vergleichen Quelldatei, die Sie im Code berechnen. Wenn diese beiden nicht übereinstimmen, wird der Visual Studio-Debugger die Skriptdatei nicht korrekt aufnehmen.

Beachten Sie auch, dass wenn Sie SourceText.From(Stream, Encoding) verwenden, versucht es detect the correct encodingfor you.

Also, wenn meine Vermutung richtig ist, sollte die SourceTree wie dies immer Ihr Problem zu lösen, wie gut:

SyntaxTree encoded; 
using(var stream = File.OpenRead(scriptPath)) 
{ 
    SourceText text = SourceText.From(stream, Encoding.UTF8); 
    encoded = CSharpSyntaxTree.ParseText(text, null, scriptPath); 
}