我正在尝试(最终)为长时间运行的 .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 对象上已经调用之后,如何以编程方式发送它?本质上是为了复制坐在控制台前的用户,但不是用户,而是一个程序。