How to debug/break in codedom compiled code
Asked Answered
I

2

22

I have an application which loads up c# source files dynamically and runs them as plugins. When I am running the main application in debug mode, is it possible to debug into the dynamic assembly? Obviously setting breakpoints is problematic, since the source is not part of the original project, but should I be able to step into, or break on exceptions for the code?

Is there a way to get codedom to generate PDBs for this or something?

Here is the code I am using for dynamic compliation.

CSharpCodeProvider codeProvider = new CSharpCodeProvider(new Dictionary<string, string>() { { "CompilerVersion", "v3.5" } });
//codeProvider.
ICodeCompiler icc = codeProvider.CreateCompiler();

CompilerParameters parameters = new CompilerParameters();
parameters.GenerateExecutable = false;
parameters.GenerateInMemory = true;
parameters.CompilerOptions = string.Format("/lib:\"{0}\"", Application.StartupPath);
parameters.ReferencedAssemblies.Add("System.dll");
parameters.ReferencedAssemblies.Add("System.Core.dll");


CompilerResults results = icc.CompileAssemblyFromSource(parameters, Source);
DLL.CreateInstance(t.FullName, false, BindingFlags.Default, null, new object[] { engine }, null, null);
Incommodious answered 17/5, 2009 at 23:21 Comment(3)
Out of curiosity (I've never really messed with the CodeDom stuff) what happens if you try to put a System.Diagnostics.Debugger.Break(); somewhere in your code? Can you then step into it?Imminence
this worked, but only with the options in the accepted answer.Incommodious
I duplicated this question per inadvertence (codedom was not the keywork I looked for). #1594420. I added a solution involving an interface. Hope it helps...Nkrumah
C
40

Try the following options:

parameters.GenerateInMemory = false; //default
parameters.TempFiles = new TempFileCollection(Environment.GetEnvironmentVariable("TEMP"), true);
parameters.IncludeDebugInformation = true;

I am not sure if this works OK in your case, but if it does, you can surround this parameters with conditional compilation directive, so that it dumps the generated assembly only in debug mode.

Circumsolar answered 18/5, 2009 at 0:6 Comment(3)
It's 2.42 years later, but you sir, are AWESOME!Passkey
It saved my time to find out the issue :)Distinction
It's 11 years later, and this information is still pure gold. Thanks!Ragouzis
S
11

The answer by @bbmud is correct, though it misses one bug fix. The CSharpCodeGenerator (the class in .NET the compiles C# code to IL) is set to remove pdb files immediately after they are created, UNLESS you add /debug:pdbonly to the CompilerOptions string. However, if you do that, the IncludeDebugInformation flag is ignored and the compiler generates optimised code which is hard to debug. To avoid this you must explicitly tell the Code Generator to keep all files.

Here is the complete recipe:

parameters.GenerateInMemory = false; //default
parameters.TempFiles = new TempFileCollection(Environment.GetEnvironmentVariable("TEMP"), true);
parameters.IncludeDebugInformation = true;
parameters.TempFiles.KeepFiles = true

Here is the culprit part of the code of CSharpCodeGenerator:

  string fileExtension = "pdb";
    if ((options.CompilerOptions != null) && (CultureInfo.InvariantCulture.CompareInfo.IndexOf(options.CompilerOptions, "/debug:pdbonly", CompareOptions.IgnoreCase) != -1))
    {
        results.TempFiles.AddExtension(fileExtension, true);
    }
    else
    {
        results.TempFiles.AddExtension(fileExtension);
    }

The TempFiles.AddExtension(fileExtension, true) tells the compile to keep the pdb files. The else option of results.TempFiles.AddExtension(fileExtension); tells it to treat pdb as all temporary files which by default means delete them.

Squier answered 25/11, 2009 at 14:9 Comment(1)
The second argument in TempFileCollection (named "keepFiles") already sets the KeepFiles property to true. (or at least it does so in .NET 4.0)Truitt

© 2022 - 2024 — McMap. All rights reserved.