在 C# 中的 CMD 中确定命令是否已执行完毕

Determine if a command has been finished executing in CMD in C#

简介

我正在使用 TCP 客户端-服务器配置在 c# 中创建一个 R.A.T(远程管理工具)。 一切都很顺利,直到我意识到需要检测命令是否已在我的 C# 应用程序创建的命令提示符进程中完成执行。 请看下面的代码。

private static Process CMDProc = null;
private static StreamWriter ToCMDShell = null;

public static void StartCMD()
{
       ProcessStartInfo PSInfo = new ProcessStartInfo
       {
             FileName = "cmd.exe",
             CreateNoWindow = true,
             UseShellExecute = false,
             RedirectStandardInput = true,
             RedirectStandardOutput = true,
             RedirectStandardError = true
       };

       CMDProc = new Process { StartInfo = PSInfo };
       CMDProc.Start();
       ToCMDShell = CMDProc.StandardInput;
       ToCMDShell.AutoFlush = true;
       CMDProc.BeginOutputReadLine();
       CMDProc.BeginErrorReadLine();
       CMDProc.OutputDataReceived += (s, e) => { /*Do something with e.Data*/ };
       CMDProc.ErrorDataReceived += (s, e) => { /*Do something with e.Data*/ };
       ToCMDShell.WriteLineAsync("ping 8.8.8.8"); //Execute a long running command in cmd terminal.
}

我想要实现的目标

您可能猜到 ping 命令需要不同的时间才能完成,具体取决于互联网连接的速度,现在我想要的是 运行 一个名为 CMDCommandExecuted() 的方法,当长时间运行像“ping”这样的 ning 命令在使用 c# 代码调用的终端中完成执行 ToCMDShell.WriteLineAsync("any dos command to execute");

到目前为止我尝试了什么

我试图从 CMDProc.OutputDataReceived 事件处理程序接收到的输出流中读取 e.Data 但没有成功,因为可能是其他一些长 运行ning 命令而不是ping 根本没有数据写入输出流,因此它不是防弹解决方案。 是的,我也曾尝试在互联网上搜索我的解决方案,但没有成功! 这就是为什么我在这里寻求您的帮助。

使用CMDProc.WaitForExit()等待完成,CMDProc.ExitCode获取最终状态码。

如果您从流中获得一些数据表明进程已挂起、冻结或需要终止,请调用 CMDProc.Kill()

如果您从流中获得一些数据表明您应该做其他事情,您可以生成其他进程或向该进程发送额外的 WriteLine 调用以进行进一步处理。

以下程序将 ping 命令输出正确发送回给我。也许您只需要等待命令或控制台读取行来给它时间。

using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

namespace MyNamespace
{
    class Program
    {
        private static Process CMDProc = null;
        private static StreamWriter ToCMDShell = null;

        public static void Main()
        {
            StartCMD();
        }    

        public static void StartCMD()
        {
            ProcessStartInfo PSInfo = new ProcessStartInfo
            {
                FileName = "cmd.exe",
                CreateNoWindow = true,
                UseShellExecute = false,
                RedirectStandardInput = true,
                RedirectStandardOutput = true,
                RedirectStandardError = true
            };

            CMDProc = new Process { StartInfo = PSInfo };
            CMDProc.Start();
            ToCMDShell = CMDProc.StandardInput;
            ToCMDShell.AutoFlush = true;
            CMDProc.BeginOutputReadLine();
            CMDProc.BeginErrorReadLine();
            CMDProc.OutputDataReceived += (s, e) =>
            {
                Console.WriteLine("PROC: {0}", e.Data);
                if (e.Data != null && e.Data.Contains("Average ="))
                {
                    // last line, you don't have to exit here, you could do something else instead...
                    ToCMDShell.WriteLine("exit");
                }
            };
            CMDProc.ErrorDataReceived += (s, e) => Console.WriteLine("PROC ERR: {0}", e.Data);
            ToCMDShell.WriteLine("ping 8.8.8.8"); //Execute a long running command in cmd terminal.
            CMDProc.WaitForExit();
            Console.WriteLine("Job done, press ENTER to quit");
            Console.ReadLine();
        }
    }
}

看起来 WriteLineAsync 直到长 运行 命令完成后才完成(例如,命令 window 已准备好接受新输入),因此您只需要 Wait on the return from WriteLineAsync 当你需要发送更多的数据,或者知道之前的命令已经完成。

private static Process CMDProc = null;
private static StreamWriter ToCMDShell = null;

public static void StartCMD() {
    ProcessStartInfo PSInfo = new ProcessStartInfo {
        FileName = "cmd.exe",
        Arguments = "/k",
        CreateNoWindow = false,
        UseShellExecute = false,
        RedirectStandardInput = true,
        RedirectStandardOutput = true,
        RedirectStandardError = true
    };

    CMDProc = new Process { StartInfo = PSInfo };
    CMDProc.Start();
    ToCMDShell = CMDProc.StandardInput;
    ToCMDShell.AutoFlush = true;
    CMDProc.BeginOutputReadLine();
    CMDProc.BeginErrorReadLine();
    CMDProc.OutputDataReceived += (s, e) => Console.WriteLine(e.Data);
    CMDProc.ErrorDataReceived += (s, e) => Console.WriteLine($"ERR: {e.Data}");

    var run = ToCMDShell.WriteLineAsync("ping 8.8.8.8"); //Execute a long running command in cmd terminal.
    // do some stuff
    run.Wait(); // wait for long command to complete
    ToCMDShell.WriteLine("exit"); //Done
}