我刚创建了一个基本的控制台应用程序,它使用我的框架从文本文件中编译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);
}
}
在调用方法时,是否有某种方法可以使控制台应用程序保持活动状态? (例如,显示的表格)
答案 0 :(得分: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(&#34; Click&#34;); 输入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);
祝你好运!