从生成它的应用程序内调试生成的.NET程序集 [英] Debugging a generated .NET assembly from within the application that generated it

查看:161
本文介绍了从生成它的应用程序内调试生成的.NET程序集的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

简单的问题:如何调试在生成程序的调试会话期间生成的代码? (见下面的代码)



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



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



我从 http://www.csharpfriends.com/Articles/getArticle.aspx?articleID=118 作为基础,并修复已过时的电话。除此之外,我在内存中生成了组件,呼叫运行良好。我明确地生成了一个包含Debug信息的程序集,这给我的希望如何:为什么不可能有调试的选项?

 使用系统; 
使用System.Text;
使用System.IO;
使用Microsoft.CSharp;
使用System.CodeDom.Compiler;
使用System.Reflection;

命名空间DynamicAssembly
{
class CreateCompileExecute
{
[STAThread]
static void Main(string [] args)
{
//创建一个文本文件来存储新的类
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(\CSharpFriends类型被构造\);});
builder.AppendLine(public void HelloWorld(){+
Console.WriteLine(\Hello World - CSharpFriends.Com Rocks.\);});
builder.AppendLine(});
builder.AppendLine(});

//创建C#编译器
CSharpCodeProvider csCompiler = new CSharpCodeProvider();

//为编译器输入参数
CompilerParameters compilerParams = new CompilerParameters();
compilerParams.OutputAssembly =CSharpFriends.dll;
compilerParams.GenerateInMemory = true;
compilerParams.IncludeDebugInformation = true;
compilerParams.ReferencedAssemblies.Add(system.dll);
compilerParams.GenerateExecutable = false; //生成DLL

//运行编译器并构建程序集
CompilerResults results = csCompiler.CompileAssemblyFromSource(
compilerParams,builder.ToString());

//将生成的程序集加载到ApplicationDomain
程序集asm = results.CompiledAssembly;
键入t = asm.GetType(CSharpFriendsRocks.CSharpFriends);

// BindingFlags枚举指定控制绑定的标志和
//通过反射进行搜索成员和类型的方式。
//以下指定绑定类型的访问控制
BindingFlags bflags = BindingFlags.DeclaredOnly | BindingFlags.Public
| BindingFlags.NonPublic | BindingFlags.Instance;

//构造类型的实例并调用成员方法
对象obj = t.InvokeMember(HelloWorld,bflags |
BindingFlags.CreateInstance,null,null,空值);

//调用方法
t.InvokeMember(HelloWorld,bflags | BindingFlags.InvokeMethod,
null,obj,null);
}
}
}


解决方案

我发现我的问题发现我的问题与如何调试/打破编码代码,这对我来说并不明显。 bbmud在这里提供了一个非常好的提示,让调试器工作正常,但没有告诉如何进入代码。我添加了一些包含我想在脚本中实现的接口的程序集的引用:

  compilerParams.ReferencedAssemblies.Add(typeof (IScript).Assembly.Location); 
compilerParams.GenerateExecutable = false; //生成DLL

//如果要调试,这是必需的...
compilerParams.GenerateInMemory = false;
compilerParams.TempFiles = new TempFileCollection(Environment。
GetEnvironmentVariable(TEMP),true);

现在,当我考虑 CSharpFriends IPlugin ,我可以通过投入上面的 obj 获得界面:

  IPlugin script = obj as IPlugin; 

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

  System.Diagnostics.Debugger.Break();脚本代码中的

也可以正常工作,但需要更改脚本。由于应用程序中的代码总是需要根据某些机制(使用属性或接口反射)知道脚本中的哪些方法,使用两者已知的接口对我来说是一个非常可以接受的解决方案。



我希望它有助于别人。


The question in short: How can I debug the code generated during a debugging session on the generating program? (see code below)

I am facing the following issue: I would like to debug into dynamically generated/compiled code from the application that generates it. I provided an oversimplified example to clarify it. This example doesn't need debugging! My real app generates many more lines and code that really justify debugging, believe me :-) I would like to know if there is a way to debug or put a breakpoint at HelloWorld. Stepping into the InvokeMethod call doesn't work. Maybe a solution involves code modification at the call sites to the generated assembly.

I had a look at many questions already (Debug dynamically loaded assembly in Visual Studio .NET for example) but none was helpful in solving the problem (if solvable at all?)

I took code from http://www.csharpfriends.com/Articles/getArticle.aspx?articleID=118 as a base and fixed the obsoleted calls. Beside this I generated the assembly on-the-fly in memory and the calls are working well. I generated explicitly an assembly with Debug information, what gives me hope: why would there be the option if debugging is not possible?

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);
        }
    }
}

解决方案

I finally found a way to workaround it after discovering that my question was a duplicate of How to debug/break in codedom compiled code, which was not obvious for me to find. bbmud gives a very good hint in there to get the debugger working correctly, but doesn't tell how to get into the code. I add a reference to some assembly containing an interface that I want to implement in the scripts:

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);

Now when I consider CSharpFriends being an implementation of IPlugin, I can get the interface by casting the obj above:

IPlugin script = obj as IPlugin;

Then debugging calls to interface methods or properties is as easy as usual! The trick of adding

 System.Diagnostics.Debugger.Break();

inside the script code also works well but it needs change to the script. As the code inside the application always needs to know what kind of methods are inside the script according to some mechanism (reflexion with attributes or interfaces), using an interface known by both is a very acceptable solution for me.

I hope it helps somebody else.

这篇关于从生成它的应用程序内调试生成的.NET程序集的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆