1

I am adding scripting possibility to my app. Init method loads the script, compiles it and calls scripts Init method. I would like to be able to attach Visual Studio debugger to my app and add breakpoints in script the usual way in the IDE.

Visual Studio says: Loaded 'i0uu5bcn.vhy'. Cannot find or open the PDB file.

The breakpoints work if used like: 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();
        }
stepandohnal
  • 457
  • 4
  • 13

1 Answers1

4

Make double sure that the file is in fact UTF8 encoded. The encoding is used to get the input bytes for the hashing function that is used when generating the PDB. Note, that Encoding.UTF8 assumes the file has BOM.

You can dump the checksums from the generated PDB (save it to disk first...) using SourceLink:

sourcelink checksums -p <pdbfile>

You can compare the value for your script file in the dump against a hash of your source file you calculate in code. Unless those two don't match, Visual Studio's debugger won't pick up the script file correctly.

Also note, that if you use SourceText.From(Stream, Encoding), it tries to detect the correct encoding for you.

So if my hunch is correct, getting the SourceTree like this should solve your issue as well:

SyntaxTree encoded;
using(var stream = File.OpenRead(scriptPath))
{
     SourceText text = SourceText.From(stream, Encoding.UTF8);
     encoded = CSharpSyntaxTree.ParseText(text, null, scriptPath);
} 
Community
  • 1
  • 1
m0sa
  • 10,712
  • 4
  • 44
  • 91