[英]Keeping a console application alive in C#
我刚刚创建了一个基本的控制台应用程序,该应用程序使用我的框架从文本文件编译C#代码。
运行此方法的方式是“ SecureCodeBridge.exe File.txt”,此文本文件包含创建并显示正常工作的Windows窗体的代码。
问题在于,因为我的应用程序是控制台应用程序,所以它将在调用文本文件中的方法后立即退出(窗体显示一秒钟,并在控制台应用程序退出时消失……)
这是我的控制台应用程序的代码:
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);
}
}
在调用该方法时,是否有某种方法可以使控制台应用程序保持活动状态? (例如,显示一个表单)
Invoke
将等待方法完成, BeginInvoke
将异步运行它,因此您的方法正在完成(例如,打开Form),然后退出控制台应用程序。
如果要等待启动的应用程序/程序集退出,则可以将其作为进程(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()),然后通过反射将其连接到控制台应用程序中的等待机制,以在接收到回调时关闭它。 从这篇文章 。
//获取代表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);
祝好运!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.