从生成它的应用程序中调试生成的.NET程序集

简而言之:如何在生成程序上调试调试会话期间生成的代码? (见下面的代码)

我面临以下问题:我想从生成它的应用程序调试动态生成/编译的代码。 我提供了一个简单的例子来澄清它。 这个例子不需要调试! 我真正的应用程序生成更多的行和代码,真正certificate调试,相信我:-)我想知道是否有一种方法可以在HelloWorld上调试或设置断点。 单步调用InvokeMethod调用不起作用。 也许解决方案涉及在调用站点对生成的程序集进行代码修改。

我已经看了很多问题(例如, 在Visual Studio .NET中调试动态加载的程序集 ),但没有一个有助于解决问题(如果可以解决的话?)

我从http://www.csharpfriends.com/Articles/getArticle.aspx?articleID=118中获取代码作为基础并修复了已废弃的调用。 除此之外,我在内存中即时生成了程序集,并且调用运行良好。 我明确地生成了一个包含Debug信息的程序集,这给了我希望:为什么在没有调试的情况下会有选项呢?

 using System; using System.Text; using System.IO; using Microsoft.CSharp; using System.CodeDom.Compiler; using System.Reflection; namespace DynamicAssembly { class CreateCompileExecute { [STAThread] static void Main(string[] args) { // Creates a text file to store the new class StringBuilder builder = new StringBuilder(); builder.AppendLine("using System;"); builder.AppendLine("namespace CSharpFriendsRocks"); builder.AppendLine("{"); builder.AppendLine("class CSharpFriends"); builder.AppendLine("{"); builder.AppendLine("public CSharpFriends() {" + " Console.WriteLine(\"The CSharpFriends type is constructed\"); }"); builder.AppendLine("public void HelloWorld() {" + " Console.WriteLine(\"Hello World - CSharpFriends.Com Rocks.\"); }"); builder.AppendLine("}"); builder.AppendLine("}"); // Create the C# compiler CSharpCodeProvider csCompiler = new CSharpCodeProvider(); // input params for the compiler CompilerParameters compilerParams = new CompilerParameters(); compilerParams.OutputAssembly = "CSharpFriends.dll"; compilerParams.GenerateInMemory = true; compilerParams.IncludeDebugInformation = true; compilerParams.ReferencedAssemblies.Add("system.dll"); compilerParams.GenerateExecutable = false; // generate the DLL // Run the compiler and build the assembly CompilerResults results = csCompiler.CompileAssemblyFromSource( compilerParams, builder.ToString()); // Load the generated assembly into the ApplicationDomain Assembly asm = results.CompiledAssembly; Type t = asm.GetType("CSharpFriendsRocks.CSharpFriends"); // BindingFlags enumeration specifies flags that control binding and // the way in which the search for members and types is conducted by reflection. // The following specifies the Access Control of the bound type BindingFlags bflags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; // Construct an instance of the type and invoke the member method Object obj = t.InvokeMember("HelloWorld", bflags | BindingFlags.CreateInstance, null, null, null); // Call the method t.InvokeMember("HelloWorld", bflags | BindingFlags.InvokeMethod, null, obj, null); } } } 

我终于找到了一种方法来解决它后发现我的问题是如何在编码的编译代码中调试/中断的重复,这对我来说并不明显。 bbmud在那里提供了一个非常好的提示,以使调试器正常工作,但不告诉如何进入代码。 我添加了对包含我想在脚本中实现的接口的程序集的引用:

 compilerParams.ReferencedAssemblies.Add(typeof(IScript).Assembly.Location); compilerParams.GenerateExecutable = false; // generate the DLL // if you want to debug, this is needed... compilerParams.GenerateInMemory = false; compilerParams.TempFiles = new TempFileCollection(Environment. GetEnvironmentVariable("TEMP"), true); 

现在当我认为CSharpFriendsIPlugin一个实现时,我可以通过上面的obj来获取接口:

 IPlugin script = obj as IPlugin; 

然后调试接口方法或属性就像平常一样简单! 添加的诀窍

  System.Diagnostics.Debugger.Break(); 

在脚本代码内部也运行良好,但它需要更改脚本。 由于应用程序内部的代码总是需要根据某种机制(使用属性或接口反思)知道脚本中有哪种方法,因此使用两者都知道的接口对我来说是一个非常可接受的解决方案。

我希望它可以帮助别人。

Visual Studio 2010在调试器中轻轻处理。 我升级后对此感到惊讶。 我希望它有所帮助。