0

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

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

我的目标.NET 5.0和使用Microsoft.PowerShell.SDK

下面是我的代码

托管程序

注意这里第 15 行, Console.WriteLine("Started");, 将执行,但以下语句(包括和 after 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);
        }
    }
}

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

4

0 回答 0