2009-10-20 11 views
11

Soru kısaca: Oluşturma programında bir hata ayıklama oturumu sırasında oluşturulan kodu nasıl ayıklayabilirim? (aşağıdaki paragrafa bakın)Oluşturulan bir uygulama içinden oluşturulan .NET derlemesini hata ayıklama

Şu sorunla karşılaşıyorum: Oluşturduğu uygulamadan dinamik olarak oluşturulmuş/derlenmiş kodda hata ayıklamak istiyorum. Netleştirmek için çok basitleştirilmiş bir örnek verdim. Bu örnek hata ayıklamaya ihtiyaç duymuyor! Benim gerçek app gerçekten hata ayıklama haklı, daha fazla satır ve kod üretir :-) bana hata ayıklamak veya HelloWorld bir kesme noktası koymak için bir yol olup olmadığını bilmek istiyorum. InvokeMethod çağrıya adım atılmıyor. Belki de bir çözüm, çağrı sitelerinde oluşturulan derlemede kod değiştirmeyi içerir.

Zaten birçok soru (örneğin Debug dynamically loaded assembly in Visual Studio .NET) bir göz vardı ama hiçbiri sorununun çözümünde yardımcı oldu (çözülebilir hiç değilse?)

Ben bir üs olarak http://www.csharpfriends.com/Articles/getArticle.aspx?articleID=118 kodu alıp talep edilmeyen aramaları sabit. Bunun yanında montajı anında bellekte oluşturdum ve aramalar iyi çalışıyor. Hata ayıklama bilgisi ile açıkça bir derleme oluşturdum, bana ne umudu veriyor: hata ayıklama mümkün değilse neden seçenek var?

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'i gördünüz mü? –

+0

Gerçekten de içine hata ayıklamak istiyorum IL kodunu görselleştirmek değil ya da bir şey mi özledim? – jdehaan

+0

Yoksa burada mümkün olmayan cevapları mı kastediyorsunuz? – jdehaan

cevap

9

Sonunda benim soru beni bulmak için belli değildi How to debug/break in codedom compiled code birinin kopyası, olduğunu keşfettikten sonra buna bir çözüm bulmak için bir yol bulduk. bbmud, hata ayıklayıcının düzgün çalışmasını sağlamak için oraya çok iyi bir ipucu verir, ancak kodun nasıl kullanıldığını anlatmaz. Ben komut uygulamak istediğiniz bir arayüz içeren bazı derlemesine ekleyin:

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

Şimdi CSharpFriendsIPlugin bir uygulama olmaktan göz önüne aldığımızda, ben obj yukarıda döküm yoluyla arayüzü alabilirsiniz:

IPlugin script = obj as IPlugin; 

Arabirim yöntemlerine veya özelliklerine yapılan çağrıları hata ayıklamak her zamanki kadar kolay! komut dosyası kodu içine

System.Diagnostics.Debugger.Break(); 

ekleme hile da iyi çalışıyor ama senaryoya değişime ihtiyacı var. Uygulamanın içindeki kodun, her zaman, her iki yöntem tarafından bilinen bir arabirim kullanılarak, bazı mekanizmalara (özniteliklere veya arabirimlere sahip yansıma) göre komut dosyasının içinde ne tür yöntemlerin bulunduğunu bilmesi gerektiğinden, benim için çok kabul edilebilir bir çözümdür.

Umarım başka birine yardımcı olur.

+0

Program sonlandırıldıktan sonra diskte kalan geçici dosyalar ile uğraşıyorum. TempFileCollection'ın 2. parametresini false değerine ayarlamak, hata ayıklama artık işe yaramazsa bir seçenek değildir. Dosyaların elden çıkarılmasını (IDisposable application) yapıyorum ve AppDomains'i buna göre işlemek zorundayım. – jdehaan

+0

Debugger.Break() hakkında da düşündüm. :) –

0

Visual Studio 2010, bu hata ayıklayıcısında yavaşça ele alır. İyileştirdikten sonra şaşırdım. Umut ediyorum bu yardım eder.