这已经让我发疯一整天了。我不确定我是否在这里做了一些愚蠢的事情,但我尝试过的所有标准解决方案和解决方法都没有任何积极的结果。我很抱歉提出了与许多已经存在的问题类似的问题,但是我的所有查询都受到更多相同类型的解决方案的欢迎,如下所示,遗憾的是,这些代码片段在我的具体情况下没有任何效果。也许这个过程本身有些特殊。
目标非常简单:我有一个外部进程 (.exe),我想以编程方式向其发送输入。
重定向输出没有任何问题:程序启动,我在屏幕上得到预期的输出。如果我专注于该过程并手动给出输入(键入命令并按 Enter),程序也会按预期响应:它以特定格式回显命令。然而,由于某种原因,下面的自动“测试”语句不会返回。它们也不会出现在应用程序本身中,因此我确信该程序根本不会收到任何内容。
我在这里做错了什么?
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
using System.Threading;
namespace Factorio_AutomatedAdmin
{
class Program
{
static void Main(string[] args)
{
var workingDir = @"E:\Program Files (x86)\Steam\steamapps\common\Factorio\bin\x64\";
var psi = new ProcessStartInfo
{
UseShellExecute = false,
RedirectStandardError = true,
RedirectStandardOutput = true,
RedirectStandardInput = true,
StandardErrorEncoding = Encoding.UTF8,
StandardOutputEncoding = Encoding.UTF8,
WindowStyle = ProcessWindowStyle.Hidden,
CreateNoWindow = true,
WorkingDirectory = workingDir,
FileName = $"{workingDir}factorio",
Arguments = @"--server-settings server-settings.json --start-server server.zip"""
};
var process = new Process
{
StartInfo = psi,
EnableRaisingEvents = true
};
process.Start();
process.OutputDataReceived += (o, e) =>
{
var err = "";
if (e.Data == null) err = e.Data;
else Console.WriteLine(e.Data);
};
process.BeginOutputReadLine();
process.ErrorDataReceived += (o, e) =>
{
var err = "";
if (e.Data == null) err = e.Data;
else Console.WriteLine(e.Data);
};
process.BeginErrorReadLine();
StreamWriter sw = process.StandardInput;
while (true)
{
sw.WriteLine("Test");
Thread.Sleep(1000);
}
}
}
}
预先感谢您的帮助!
更新: 仍然无法在 C# 中运行,但是下面的 PowerShell 代码确实达到了预期的效果:
$dir = "E:\Program Files (x86)\Steam\steamapps\common\Factorio\bin\x64\"
$serverPath = $dir + "factorio.exe"
$spectator = "Tybs"
Set-Location -Path $dir
$psi = New-Object System.Diagnostics.ProcessStartInfo;
$psi.FileName = $serverPath; #process file
$psi.UseShellExecute = $false; #start the process from it's own executable file
$psi.RedirectStandardInput = $true; #enable the process to read from standard input
$psi.RedirectStandardOutput = $true; #enable the process to read from standard output
$psi.RedirectStandardError = $true;
$psi.Arguments = '--server-settings "E:\Program Files (x86)\Steam\steamapps\common\Factorio\bin\x64\server-settings.json" --start-server tybsania.zip'
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $psi
# Register Object Events for stdin\stdout reading
$OutEvent = Register-ObjectEvent -Action {
$data = $Event.SourceEventArgs.Data
Write-Host $data
return $data
} -InputObject $p -EventName OutputDataReceived -MessageData $players
$ErrEvent = Register-ObjectEvent -Action {
Write-Host $Event.SourceEventArgs.Data
} -InputObject $p -EventName ErrorDataReceived
[void]$p.Start()
$p.BeginOutputReadLine();
$p.BeginErrorReadLine();
while($true)
{
$cmd = Read-Host "Command"
$p.StandardInput.WriteLine($cmd)
}
这至少是一个解决方法。不过,如果有人有 C# 的答案,我很想听听:这会给我更多的选择。
我使用 python 和 node 遇到了同样的问题。显然,如果异星工厂是从控制台应用程序生成的,它会将其标准输入重新附加到控制台输入。令人困惑的是,当直接从控制台启动时不起作用。
无论如何,我能够通过使用 pythonw.exe 启动我的脚本来解决 python 中的问题,该脚本在用户模式下运行,而不是作为控制台程序运行。
如果您将 C# 应用程序构建为用户模式应用程序,我敢打赌这会解决该问题。