Запись ввода в процесс - RedirectStandardInput не работает - PullRequest
0 голосов
/ 18 апреля 2020

Это сводило меня с ума на весь день. Я больше не уверен, делаю ли я здесь что-то глупое, но все стандартные решения и обходные пути, которые я попробовал, безрезультатны. Я прошу прощения за вопрос, похожий на многие уже существующие, но все мои запросы встречаются с большим количеством решений того же типа, как показано ниже, фрагментов кода, которые, к сожалению, не имеют никакого эффекта в моем конкретном случае c. Может быть, это что-то особенное в самом процессе.

Цель очень проста: у меня есть внешний процесс (.exe), на который я хочу программно отправлять ввод.

Перенаправление вывода происходит без каких-либо проблем: программа запускается, и я получаю ожидаемый результат на экране. Если я сфокусируюсь на процессе и вручную введу данные (введите команду и нажмите клавишу ввода), программа также отреагирует так, как ожидалось: она выведет команду обратно в указанном формате c. Тем не менее, автоматические «Test» заявления ниже не возвращаются по какой-то причине. Они также не отображаются в самом приложении, поэтому я уверен, что программа вообще ничего не получает.

Что я здесь не так делаю?

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#, я бы хотел услышать его: это даст мне больше возможностей для работы.

...