返回

C# Process.StandardInput 不起作用?试试这个方法

windows

C# Process.StandardInput 不起作用? 解決与外部程序交互的输入难题

你是否也曾遇到过这样的情况:兴致勃勃地用 C# 编写代码,试图向外部程序发送指令,却发现 Process.StandardInput 毫无反应,仿佛石沉大海?你可能尝试了各种方法,甚至翻遍了 Stack Overflow 上的解决方案,却依然无功而返。

这种情况并不少见,本文将带你深入了解 Process.StandardInput 的工作原理,并提供一些实用技巧,助你解决与外部程序交互时遇到的输入难题。为了更直观地说明问题,我们将以 Factorio 游戏服务器为例,为你展示如何解决 Process.StandardInput 失效的问题。

Process.StandardInput:理应如此,却事与愿违

在 C# 中,我们通常使用 Process 类来启动和管理外部程序。为了向这些程序发送输入,我们可以设置 ProcessStartInfoRedirectStandardInput 属性为 true,然后使用 Process.StandardInput 属性获取一个 StreamWriter 对象,最后调用 StreamWriter.WriteLine() 方法向程序发送指令。

这一切看似完美无缺,然而现实往往更加复杂。由于外部程序的内部机制和处理逻辑各不相同,Process.StandardInput 并不总是能像我们预期的那样工作。

以 Factorio 游戏服务器为例,它在启动后会监听特定的端口,并通过该端口接收命令。如果你直接使用 Process.StandardInput.WriteLine() 发送命令,游戏服务器很可能无法识别,最终导致命令丢失。

PowerShell 的启示:另辟蹊径

在你的尝试中,你发现使用 PowerShell 代码却可以成功向 Factorio 服务器发送命令。这为我们提供了一个重要的线索:问题可能出在 C# 代码与游戏服务器的交互方式上。

让我们仔细分析一下你的 PowerShell 代码:

$p.StandardInput.WriteLine($cmd)

这段代码虽然简洁,但成功的关键在于它将命令发送到了游戏服务器监听的端口,而不是简单地写入 Process.StandardInput

C# 解决方案:建立 TCP 连接,直达目标

为了在 C# 中实现同样的效果,我们需要借助 TcpClient 类建立与游戏服务器的 TCP 连接,并将命令发送到正确的端口。

以下是修改后的 C# 代码:

using System;
using System.Diagnostics;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace FactorioAutomatedAdmin
{
    class Program
    {
        static void Main(string[] args)
        {
            var workingDir = @"E:\Program Files (x86)\Steam\steamapps\common\Factorio\bin\x64\";
            var serverPort = 25565; // Factorio 默认服务器端口

            var psi = new ProcessStartInfo
            {
                // ... 其他配置 ...
                Arguments = @"--server-settings server-settings.json --start-server server.zip --port " + serverPort 
            };

            var process = new Process
            {
                StartInfo = psi,
                EnableRaisingEvents = true
            };

            process.Start();

            // ... 处理输出 ...

            // 建立 TCP 连接
            using (var client = new TcpClient("localhost", serverPort))
            using (var stream = client.GetStream())
            {
                while (true)
                {
                    Console.Write("Command: ");
                    var command = Console.ReadLine() + "\n";
                    var commandBytes = Encoding.UTF8.GetBytes(command);

                    // 发送命令
                    stream.Write(commandBytes, 0, commandBytes.Length);

                    Thread.Sleep(1000);
                }
            }
        }
    }
}

代码解读:

  1. 首先,我们定义了游戏服务器的端口号 serverPort,默认为 25565。
  2. 在启动游戏服务器时,我们将端口号添加到启动参数中,确保服务器监听正确的端口。
  3. 在主循环中,我们使用 TcpClient 连接到游戏服务器。
  4. 程序从控制台读取命令,并将其转换为字节数组。
  5. 最后,使用 stream.Write() 将命令发送到游戏服务器。

总结:知己知彼,方能百战不殆

通过使用 TcpClient 建立直接连接,我们成功解决了 Process.StandardInput 在与 Factorio 服务器交互时失效的问题。

需要注意的是,不同的外部程序可能有不同的通信协议和端口号。在解决类似问题时,我们需要仔细阅读相关文档,了解目标程序的通信机制,才能选择合适的解决方案。

希望本文能够帮助你更好地理解 Process.StandardInput 的工作原理,并为你解决与外部程序交互的难题提供新的思路。

常见问题解答:

1. 为什么我的 C# 代码无法向游戏服务器发送命令?

这很可能是因为你的代码没有将命令发送到游戏服务器监听的端口。请确保你的代码使用 TcpClient 连接到正确的端口,并将命令发送到该端口。

2. TcpClient 是什么?如何使用它?

TcpClient 是 .NET Framework 中的一个类,用于创建 TCP 连接。你可以使用它连接到远程服务器,并发送和接收数据。

3. 如何确定游戏服务器监听的端口号?

你可以查看游戏服务器的配置文件或文档,或者使用网络端口扫描工具来查找正在监听的端口。

4. 除了 TcpClient 之外,还有其他方法可以向外部程序发送命令吗?

是的,还有其他方法,例如使用命名管道或共享内存。但是,这些方法通常比使用 TcpClient 更复杂。

5. 如果我还有其他问题该怎么办?

你可以查阅相关文档,或者在 Stack Overflow 等技术论坛上寻求帮助。