C#启动一个cmd.exe多次随时输入命令并获取输出

        想要实现的效果,程序通过Process类一次启动cmd,后台线程每隔一定时间,向其输入命令,获得并处理输出。

一、基本操作

        首先,通常操作的例子一抓一大把:

1、通过Process启动cmd执行一条/多条(&&连接)命令;

2、退出(一条时可以在命令开头加“/c”自动退出,或多条时最后输入exit退出);

3、获取输出(可以一行行读,或者“读到末尾”,这里划重点)。

二、多次输入输出

        首先,Process的启动值创建出来:

ProcessStartInfo psi = new ProcessStartInfo()
{
    FileName = "C:\\Windows\\System32\\cmd.exe",
    UseShellExecute = false,
    RedirectStandardOutput = true,
    RedirectStandardInput = true,
    RedirectStandardError = true,
    CreateNoWindow = true,
};

        然后后台启动,开始进行输入:

Task.Factory.StartNew(o =>
{
    ProcessStartInfo psi = new ProcessStartInfo()
    {
        FileName = "C:\\Windows\\System32\\cmd.exe",
        UseShellExecute = false,
        RedirectStandardOutput = true,
        RedirectStandardInput = true,
        RedirectStandardError = true,
        CreateNoWindow = true,
    };
    using (var _cmd = Process.Start(psi))
    {
        _cmd.StandardInput.AutoFlush = true;
        while (true)
        {
            Thread.Sleep(2000);
            GetSocketPair();
        }
    }
}, this, null, TaskCreationOptions.LongRunning, TaskScheduler.Default);

//你的代码,笔者这里是要获取当前进程下TCP连接数量
private void GetSocketPair()
{
    if (_cmd == null) return;
    string cmd = $"netstat -ano | findstr {Process.GetCurrentProcess().Id} |findstr TCP |find /C /V \"\"";
    string socketPairCount = WriteCmd(cmd);
}

//输入并获取输出的核心逻辑
private string WriteCmd(string cmd)
{
    //重点1,自定义结束符号
    string suffix = "###";
    string output = "";
    //一行命令变两行,主要使用自定义结束符号,作为输入的结束标志,同样也是输出的起始标志(在正则匹配时)
    if (!cmd.EndsWith(suffix))
        cmd += $"&& echo {suffix}";
    _cmd.StandardInput.WriteLine(cmd);
    string line = "";
    //重点2,不能通过_cmd.StandardOutput.EndOfStream作为while的条件,因为程序未exit退出,不在流的末尾,该状态一直为false
    //输出的结束标志,此时第二条echo自定义结束符号的命令已执行完毕
    while(!line.StartsWith(suffix))
    {
        //重点3,不能通过_cmd.StandardOutput.ReadToEnd读取内容,与重点2原理相同,ReadToEnd需要流结束了才可以
        line = _cmd.StandardOutput.ReadLine();
        if (!string.IsNullOrEmpty(line))
            output += line+"\r";
    }
    Regex r = new Regex(@"###.*###");
    string result = r.Match(output).Value;
    //掐头去尾回车符号\r
    result = result.Replace(suffix, "").TrimStart('\r').TrimEnd('\r');
    return result;
}

        同样的,后台线程启动后,其他线程也可以调用WriteCmd方法执行指令,不过要注意线程安全,主要可能的问题是输出返回给错误的调用方。

        如有多线程的需要,可以通过使用lock(await/async异步方法中不适用)、信号量等线程同步基元以保证线程安全。

  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值