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);
}
}
} |
|