设为首页收藏本站
查看: 3477|回复: 0

[高级语言] C# 后台调用 CMD 执行命令

[复制链接]
  • TA的每日心情
    奋斗
    2022-8-5 08:00
  • 签到天数: 265 天

    [LV.8]以坛为家I

    发表于 2021-11-9 19:15:09 | 显示全部楼层 |阅读模式
    C# 后台调用 CMD 执行命令
    有时会在程序中调用系统的命令行工具 cmd.exe 来静默执行一些系统命令,然后获取返回值。本文将展示 .NET/C# 静默运行 cmd 并执行命令的方法,包括 有返回值 和 无返回值 两种。

    无返回值
    public static void Execute(string command)
    {
        var processInfo = new ProcessStartInfo("cmd.exe", "/S /C " + command)
        {
            CreateNoWindow = true,
            UseShellExecute = true,
            WindowStyle = ProcessWindowStyle.Hidden
        };

        Process.Start(processInfo);
    }

    有返回值
    public static string ExecuteWithOutput(string command)
    {
        var processInfo = new ProcessStartInfo("cmd.exe", "/S /C " + command)
        {
            CreateNoWindow = true,
            UseShellExecute = false,
            WindowStyle = ProcessWindowStyle.Hidden,
            RedirectStandardOutput = true
        };

        var process = new Process {StartInfo = processInfo};
        process.Start();
        var outpup = process.StandardOutput.ReadToEnd();

        process.WaitForExit();
        return outpup;
    }
    ————————————————
    在读取StandardOutput流时,有两种方式,即同步和异步。

    同步方式,会在读取流的一方和写入流的一方形成依赖关系,这种依赖关系形成了死锁的条件。当要写或读足够多的数据时,双方会等待对方写完或者读完,彼此的等待导致了死锁的产生。具体的解释可以参见msdn:http://msdn.microsoft.com/en-us/ ... cess.standardoutput(v=VS.80).aspx

    如果我们不需要重定向输出,可以将psi.RedirectStandardOutput设置为false。

    如果需要重定向输出,那么必须解决潜在的死锁问题,方法有两个:

    方法一:Call ReadToEnd() before WaitForExit()

    private static void ExecuteTool(string toolFile, string args)
            {
                Process p;
                ProcessStartInfo psi;
                psi = new ProcessStartInfo(toolFile);
                psi.Arguments += args;

                psi.UseShellExecute = false;
                psi.RedirectStandardOutput = true;  //允许重定向标准输出
                psi.CreateNoWindow = true;
                psi.RedirectStandardError = true;
                psi.WindowStyle = ProcessWindowStyle.Hidden;

                p = Process.Start(psi);

        string output = p.StandardOutput.ReadToEnd(); //Call ReadToEnd() before WaitForExit()

                p.WaitForExit();
                p.Close();
            }

    方法二:采用异步方式(适用于同时获取标准输出流和错误流)

    private static void ExecuteTool(string toolFile, string args)
            {
                Process p;
                ProcessStartInfo psi;
                psi = new ProcessStartInfo(toolFile);
                psi.Arguments += args;

                psi.UseShellExecute = false;
                psi.RedirectStandardOutput = true;  //允许重定向标准输出

        psi.RedirectStandardError = true;
                psi.CreateNoWindow = true;
                psi.RedirectStandardError = true;
                psi.WindowStyle = ProcessWindowStyle.Hidden;

                p = Process.Start(psi);

        p.OutputDataReceived += new DataReceivedEventHandler(OnDataReceived);
                p.BeginOutputReadLine();

                p.WaitForExit();

        if (p.ExitCode != 0)
                {
                    result.Append(p.StandardError.ReadToEnd());
                }           
                p.Close();
            }

      private static void OnDataReceived(object Sender, DataReceivedEventArgs e)
            {
                if (e.Data != null)
                {
                    result.Append(e.Data);
                }
            }

    ------------------------------------------------------------------------------------------------------------------
    这使用异步/等待来启动进程,然后使用进程输出事件来更新UI。
    using System;
    using System.ComponentModel;
    using System.Diagnostics;
    using System.Linq;
    using System.Windows.Forms;
    using System.IO;

    namespace SendInput
    {
        public partial class Form1: Form
        {
         private SynchronizationContext _syncContext;

         public Form1()
         {
          InitializeComponent();
         }

         private async void btnCommand_Click(object sender, EventArgs e)
         {
          CheckForIllegalCrossThreadCalls = false;

          await StartProcessAsync();
         }

         private Task StartProcessAsync()
         {
          return Task.Run(()=>
          {
           try
           {
            //Create Process Start information
            ProcessStartInfo processStartInfo =
             new ProcessStartInfo(@"C:\Users\devPC\Desktop\Server\run.bat");
            processStartInfo.ErrorDialog = false;
            processStartInfo.UseShellExecute = false;
            processStartInfo.RedirectStandardError = true;
            processStartInfo.RedirectStandardInput = true;
            processStartInfo.RedirectStandardOutput = true;

            //Execute the process
            Process process = new Process();
            process.StartInfo = processStartInfo;

            process.OutputDataReceived += (sender, args) => UpdateText(args.Data);
            process.ErrorDataReceived += (sender, args) => UpdateErrorText(args.Data);

            process.Start();
            process.BeginOutputReadLine();
            process.BeginErrorReadLine();
            process.WaitForExit();
           }
           catch (Exception ex)
           {
            MessageBox.Show(ex.Message);
           }
          });
         }

         private void UpdateText(string outputText)
         {
          _syncContext.Post(x => rtbConsole.AppendText("Output \n==============\n"), null);     
          _syncContext.Post(x => rtbConsole.AppendText(outputText), null);
         }

         private void UpdateErrorText(string outputErrorText)
         {
          _syncContext.Post(x => rtbConsole.AppendText("\nError\n==============\n"), null);
          _syncContext.Post(x => rtbConsole.AppendText(outputErrorText), null);
         }
        }
    }
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    红盟社区--红客联盟 

    Processed in 0.060951 second(s), 24 queries.

    站点统计| 举报| Archiver| 手机版| 黑屋 |   

    备案号:冀ICP备20006029号-1 Powered by HUC © 2001-2021 Comsenz Inc.

    手机扫我进入移动触屏客户端

    关注我们可获取更多热点资讯

    Honor accompaniments. theme macfee

    快速回复 返回顶部 返回列表