2016-04-30 4 views
1

Я добавляю возможность сценариев в свое приложение. Метод Init загружает скрипт, компилирует его и вызывает метод init. Я хотел бы иметь возможность подключать отладчик Visual Studio к моему приложению и добавлять точки останова в сценарии обычным способом в среде IDE.Загрузка символов для динамически скомпилированных сборок

Visual Studio говорит: Загружен «i0uu5bcn.vhy». Не удается найти или открыть файл PDB.

Контрольные точки работают, если они используются как: 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(); 
     } 

ответ

2

Убедитесь, что файл на самом деле закодирован в кодировке UTF8. Кодирование используется для получения входных байтов для хеширующей функции, которая используется при создании PDB. Обратите внимание, что Encoding.UTF8 предполагает, что файл имеет BOM.

Вы можете сбросить контрольные суммы из сгенерированного PDB (сохранить его на диск первого ...) с помощью SourceLink:

sourcelink checksums -p <pdbfile> 

Вы можете сравнить значение для файла сценария в дампе против хэша ваших исходный файл, который вы вычисляете в коде. Если эти два не совпадают, отладчик Visual Studio не заберет файл сценария правильно.

Также обратите внимание, что если вы используете SourceText.From(Stream, Encoding), он пытается установить detect the correct encodingfor you.

Так что, если моя догадка верна, получение SourceTree как это должно решить проблему, а также:

SyntaxTree encoded; 
using(var stream = File.OpenRead(scriptPath)) 
{ 
    SourceText text = SourceText.From(stream, Encoding.UTF8); 
    encoded = CSharpSyntaxTree.ParseText(text, null, scriptPath); 
} 
Смежные вопросы