2016-08-03 109 views
0

我剛剛創建了一個基本控制檯應用程序,它使用我的框架從文本文件編譯C#代碼。在C中保持控制檯應用程序活着#

你運行這個的方式是「SecureCodeBridge.exe File.txt」,這個文本文件包含了創建和顯示可以正常工作的窗體的代碼。

的問題是,因爲我的應用程序是一個控制檯應用程序,它會立即退出從文本文件的方法被調用(表格顯示了第二和消失的控制檯應用程序退出...)

這是我的控制檯應用程序的代碼:

static void Main(string[] args) 
{ 
    string entString = args[0]; 

    if(System.IO.File.Exists(entString)) 
    { 
     string entContents = System.IO.File.ReadAllText(entString); 
     SecureCode sC = new SecureCode(entContents); 
     CompilerResults cR = sC.Compile(); 

     if(cR.Errors.Count > 0) 
     { 
      //Abort! 
      foreach(CompilerError cE in cR.Errors) 
      { 
       Console.WriteLine(cE.ErrorText); 
      } 
     } 
     else 
     { 
      sC.Run(cR); 
     } 
    } 
} 

這是我的框架使用編譯和運行代碼的代碼:

public class SecureCode 
{ 
    string code; 
    public SecureCode(string source) 
    { 
     code = source; 
    } 

    public CompilerResults Compile() 
    { 
     Dictionary<string, string> providerOptions = new Dictionary<string, string> 
     { 
      {"CompilerVersion", "v3.5"} 
     }; 
     CSharpCodeProvider provider = new CSharpCodeProvider(providerOptions); 

     CompilerParameters compilerParams = new CompilerParameters 
     { 
      GenerateInMemory = true, 
      GenerateExecutable = false 
     }; 
     compilerParams.ReferencedAssemblies.Add("System.dll"); 
     compilerParams.ReferencedAssemblies.Add("System.Windows.Forms.dll"); 
     compilerParams.ReferencedAssemblies.Add("System.Drawing.dll"); 

     CompilerResults results = provider.CompileAssemblyFromSource(compilerParams, code); 

     return results; 
    } 

    public void Run(CompilerResults results) 
    { 
     object o = results.CompiledAssembly.CreateInstance("Code.Class"); 
     MethodInfo mi = o.GetType().GetMethod("Main"); 
     mi.Invoke(o, null); 
    } 
} 

是有些方法可以在調用方法時保持控制檯應用程序的活動? (例如,被示出的形式)

回答

2

Invoke將等待完成的方法中,BeginInvoke將異步運行,所以你的方法完成(例如打開表),然後控制檯應用程序正在退出。

如果你想等待你紡達退出應用/裝配,那麼你可以運行它是一個過程(System.Diagnostics程序),您將需要考慮如何讓你的編譯的代碼中可調用格式:

var process = Process.Start(<options>); 
process.WaitForExit(); 

另一種辦法是掛在一個弱引用,我還沒有運行以下,但它不應該是爲期不遠。你會循環播放,直到弱引用的對象被清理乾淨了,不再被視爲由垃圾收集相關:

WeakReference(weakRef = new WeakReference(results.CompiledAssembly.CreateInstance("Code.Class")); 
MethodInfo mi = weakRef.Target.GetType().GetMethod("Main"); 
mi.Invoke(o, null); 

// Wait until the application exists AND the Garbage Collector cleans it up 
while (weakRef.IsAlive) 
{ 
    Thread.Sleep(100); 
} 

我能想到的最後一個選項將是一個事件處理程序編譯(說的OnExit或OnClose中()),然後通過控制檯應用程序中的等待機制通過反射將其連接起來,以在收到回調時關閉。 From this post

//獲取表示Click事件的EventInfo,並獲取處理該事件的代理類型 。 // EventInfo evClick = tExForm.GetEvent(「Click」); 類型tDelegate = evClick.EventHandlerType;

// If you already have a method with the correct signature, 
// you can simply get a MethodInfo for it. 
// 
MethodInfo miHandler = 
    typeof(Example).GetMethod("LuckyHandler", 
     BindingFlags.NonPublic | BindingFlags.Instance); 

// Create an instance of the delegate. Using the overloads 
// of CreateDelegate that take MethodInfo is recommended. 
Delegate d = Delegate.CreateDelegate(tDelegate, this, miHandler); 

// Get the "add" accessor of the event and invoke it late- 
// bound, passing in the delegate instance. This is equivalent 
// to using the += operator in C#, or AddHandler in Visual 
// Basic. The instance on which the "add" accessor is invoked 
// is the form; the arguments must be passed as an array. 
// 
MethodInfo addHandler = evClick.GetAddMethod(); 
Object[] addHandlerArgs = { d }; 
addHandler.Invoke(exFormAsObj, addHandlerArgs); 

祝你好運!

+0

我試過第二種方法,但它保持控制檯應用程序活着(凍結)它也將凍結窗體本身,任何想法? (嘗試在不同的線程上運行它,但隨後我們又回到了原來的形式,並一直退出) – user265889

+0

在單獨的線程上運行調用到循環。弱言談仍將維持到形式超出範圍。 –