2009-10-20 10 views
11

短い質問:プログラムを生成中にデバッグセッション中に生成されたコードをどのようにデバッグできますか? (下のコードを参照してください)生成された.NETアセンブリを生成したアプリケーション内からデバッグする

私は次の問題に直面しています:それを生成するアプリケーションから動的に生成/コンパイルされたコードにデバッグしたいと思います。私はそれを明確にするための単純化された例を提供しました。この例ではデバッグは必要ありません。私の実際のアプリケーションは、デバッグを本当に正当化するより多くの行とコードを生成します:-)私はデバッグする方法があるかどうかを知りたいですか、またはブレークポイントをHelloWorldに置くことができます。 InvokeMethod呼び出しにステップインしても機能しません。たぶん、ソリューションは、コールサイトで生成されたアセンブリへのコード変更を伴います。

は、私はすでに多くの質問(例えば Debug dynamically loaded assembly in Visual Studio .NET)を見ていたが、どれも問題を解決するのに役立ちませんでした(解けるすべての場合は?)

私はベースとしてhttp://www.csharpfriends.com/Articles/getArticle.aspx?articleID=118からコードを取り、廃止された通話を固定しました。これに加えて、私はメモリ上でオンザフライでアセンブリを生成し、呼び出しはうまくいっています。私は明示的にデバッグ情報を持つアセンブリを生成しました。私に希望を与えるもの:デバッグが不可能な場合、なぜオプションがありますか?

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

あなたはhttp://stackoverflow.com/questions/321203/how-do-i-debug-il-code-generated-at-runtime-using-reflection-emitを見ましたか? –

+0

私は実際にそれをILコードを視覚化しないようにデバッグしたいのですか、何か迷っていましたか? – jdehaan

+0

それは可能ではないと答えたのですか? – jdehaan

答えて

9

私は最終的に私の質問は私が探して明らかではなかったHow to debug/break in codedom compiled codeの重複があったことを発見した後、それを回避する方法を発見しました。 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(); 

も有効ですが、スクリプトに変更する必要があります。アプリケーション内のコードは、何らかのメカニズム(属性やインターフェースによるリフレクション)によってスクリプト内にどのようなメソッドがあるかを常に知る必要があるため、両方のインターフェイスが使用できるのは私にとっては非常に受け入れやすいソリューションです。

私はそれが他の人に役立つことを望みます。

+0

私はプログラムの終了後にディスクに残っている一時ファイルに苦労しています。 TempFileCollectionの2番目のパラメータをfalseに設定することは、デバッグがもう機能しなくなるため、オプションではありません。私は、ファイルの手作業での処理(IDisposable実装)を行い、それに応じてAppDomainsを処理する必要があります。 – jdehaan

+0

Debugger.Break()についても考えました。 :) –

0

Visual Studio 2010はこれをデバッガで静かに処理します。私はアップグレードした後、私はそれに驚いた。私はそれが助けて欲しい

関連する問題