C# - 如何使用“cmd.exe”作为 BackgroundWorker Process

问题描述

我实际上是在使用回调 WCF 服务构建远程命令行(最终目标是主要通过 SteamCMD 管理和更新我的个人服务器上的游戏服务器实例)。我能够向远程服务发送命令,让它们在“cmd.exe”中运行,并成功接收到 WinForm 和 MVC 网站测试客户端的实时进度更新

enter image description here

但是,我想在必要时添加等待/提供用户输入的功能,主要是因为一些 Steam 游戏服务器不允许通过 SteamCMD 匿名登录用户需要输入他们的 Steam 密码或 2FA。我用来测试输入的一个很好的例子是 Windows 命令提示符中的“date”命令。通常,它会打印日期,然后提示用户“输入新日期”。

enter image description here

但是,当我通过我的服务运行“Date”命令时,ReadLine() 不会读取输入新日期的提示,而是无限期地等待我假设的输入。

enter image description here

我遇到的问题:

  • 如何检测进程何时等待用户输入
  • 进程没有输出通常提示用户输入的最后一行(挂在 ReadLine 上)

以下代码块是处理StdOut的Process和重定向的主要函数。 “runcommandLine”几乎启动 Process 并设置所有事件处理程序,“Processer_DoWork”处理将 StdOut 推送到 CallbackFunction 以便客户端可以实时查看输出

我的设置方式是否可以满足我的需求?我是能够实现中断功能,所以我想我能做到传递实际的输入过程类似的东西..我只是失去了对如何检测实际需要的输入。

在此先感谢您的帮助!

private BackgroundWorker Processer = new BackgroundWorker();
public IGameManagerCallback Callback;

public void runcommandLine(string WorkingPath,string Commands)
{
    if (Processer.IsBusy)
    {
        return;
    }

    Processer.WorkerReportsProgress = true;
    Processer.WorkerSupportsCancellation = true;
    Processer.ProgressChanged += Processer_ProgressChanged;
    Processer.DoWork += Processer_DoWork;
    Processer.RunWorkerCompleted += Processer_WorkComplete;
    Callback = OperationContext.Current.GetCallbackChannel<IGameManagerCallback>();


    processstartinfo StartInfo = new processstartinfo
    {
        FileName = "cmd.exe",Arguments = $@"/c {Commands}",UseShellExecute = false,RedirectStandardOutput = true,RedirectStandardError = true,RedirectStandardInput = true,CreateNowindow = true
    };

    if (!string.IsNullOrEmpty(WorkingPath))
        StartInfo.WorkingDirectory = Path.GetDirectoryName($@"{WorkingPath}");

    Process CommandProcess;
    try { CommandProcess = Process.Start(StartInfo); }
    catch (Exception ex)
    {
        Console.WriteLine($"Error starting: {ex.Message}");
        return;
    }

    //attach to background processor            
    Processer.RunWorkerAsync(CommandProcess);
}

private void Processer_DoWork(object sender,DoWorkEventArgs e)
{
    BackgroundWorker worker = (BackgroundWorker)sender;
    Process proc = e.Argument as Process;
    StreamReader StandardOutput = proc.StandardOutput;
    StreamWriter StandardInput = proc.StandardInput;
    string data = StandardOutput.ReadLine();
    while (data != null)
    {
        if (worker.CancellationPending)
        {
            e.Cancel = true;
            break;
        }

        Processer.ReportProgress(0,data);
        data = StandardOutput.ReadLine();//this is where we hang when there is input required
    }
}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)