繁体   English   中英

使控制台应用程序在C#中保持活动状态

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM