2016-08-03 73 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

在单独的线程上运行调用到循环。弱言谈仍将维持到形式超出范围。 –