| 
 
TA的每日心情|  | 奋斗 2022-8-5 08:00
 | 
|---|
 签到天数: 265 天 [LV.8]以坛为家I | 
 
| 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);
 }
 }
 }
 | 
 |