C# 在调用 Invoke()

发布时间:2021-03-07 04:17

我正在尝试(最终)为长时间运行的 .exe 应用程序(例如加密节点或游戏服务器)编写 C# 服务包装器。到目前为止,我已经编写了一个输出 .exe 输出的小型 PowerShell 主机(当前到控制台,最终它会转到其他地方)和一个小型示例应用程序,它每秒输出一次时间,并位于 Console.ReadLine() 处寻找“停止”停止执行。目前我能够托管示例应用程序并正确地将输出定向(到控制台),但我需要知道如何在调用 PowerShell.Invoke() 后添加命令。

像游戏服务器这样的程序通常有可用的命令,比如“保存”或“退出”来控制服务器。程序在托管的 PowerShell 会话中运行后,我想添加一个“停止”命令来停止示例应用程序,但我不知道如何。

我的目标是 .NET 5.0 并使用 Microsoft.PowerShell.SDK 软件包

下面是我的代码

托管程序

请注意,第 15 行 Console.WriteLine("Started"); 将执行,但以下语句(包括 Console.WriteLine("Attempting stop"); 和之后)将不会执行,或者至少不会进入控制台。

using System;
using System.Management.Automation;

namespace ServiceWrapper
{
    class Program
    {
        static void Main(string[] args)
        {
            // Create the hosting session
            var ps = PowerShell.Create();
            ps.AddScript("& C:\\Code\\SimpleServiceWrapper\\TestApplication\\SampleApp.exe");

            // Hook the output
            var output = new PSDataCollection<PSObject>();
            output.DataAdded += new EventHandler<DataAddedEventArgs>(InformationEventHandler);
            ps.Invoke(null, output);
            Console.WriteLine("Started");

            // This code is not run
            Console.WriteLine("Attempting stop");
            ps.AddStatement().AddCommand("stop");
            ps.Invoke();
        }

        // Write output live to the console
        static void InformationEventHandler(object sender, DataAddedEventArgs e)
        {
            var myp = (PSDataCollection<PSObject>)sender;
            var results = myp.ReadAll();

            foreach (PSObject result in results)
            {
                Console.WriteLine(result.ToString());
            }
        }
    }
}

示例应用

这个小应用程序的目标是模拟一个长时间运行的程序(如游戏服务器)并需要一些输入(如“停止”)才能正确退出程序。这主要是为了完整性

using System;
using System.Timers;

namespace SampleApp
{
    class SampleApp
    {
        static void Main(string[] args)
        {
            // Setup a simple 1 second timer
            var timer = new Timer(1000) { AutoReset = true };
            timer.Elapsed += TimerElapsedEventHandler;
            timer.Start();

            // loop until told to stop
            var loop = true;
            while (loop)
            {
                var stop = Console.ReadLine();
                if (stop.ToLower() == "stop")
                {
                    loop = false;
                    Console.WriteLine("Stopping");
                }
            }
        }

        // Every 1 second, write the time
        private static void TimerElapsedEventHandler(object sender, ElapsedEventArgs e)
        {
            Console.WriteLine(DateTime.Now);
        }
    }
}

由于示例程序需要读取“停止”才能正确停止,在托管 PowerShell 对象上已调用 Invoke() 后,如何以编程方式发送该内容?本质上是复制坐在控制台的用户,但不是用户,而是程序。

回答1