如何在 C# 中执行多个.BAT文件
本文关键字:BAT 文件 执行 | 更新日期: 2023-09-27 18:32:45
我需要使用"c# windows 表单应用程序"执行多个批处理文件。以防 bat 包含一行或多行,例如:"start filename.exe"我的程序会等到"文件名.exe"被终止,显然这不是我需要
的附上我使用的代码段,您将找到一个示例 Windows 窗体应用程序。
提前谢谢。
弗朗切斯科
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Sample
{
public partial class Form1 : Form
{
/*
* Batch files
*
c:'batch1.bat
echo startExecution
start /b calc.exe
echo endExecution
exit
*
*
c:'batch2.bat
echo startExecution2
start /b notepad.exe
echo endExecution2
exit
*/
public Form1()
{
//Just for sample is unsafe
Control.CheckForIllegalCrossThreadCalls = false;
InitializeComponent();
this.button1.Click += button1_Click;
}
private void button1_Click(object sender, EventArgs e)
{
this.richTextBox1.Text = "Initialized'r'n";
BatchExecution be = new BatchExecution("c:''batch1.bat");
be.endOccurs += be_endOccurs;
be.DoWork();
be = new BatchExecution("c:''batch2.bat");
be.endOccurs += be_endOccurs;
be.DoWork();
}
private void be_endOccurs(BatchExecution sender)
{
this.richTextBox1.AppendText(sender.output);
sender = null;
}
}
public class BatchExecution
{
private String batch { get; set; }
public Process process { get; private set; }
public delegate void workHasEndedHandler(BatchExecution sender);
public event workHasEndedHandler endOccurs;
private Boolean _hasEnded = false;
public Boolean hasEnded
{
get
{
return _hasEnded;
}
set
{
_hasEnded = value;
if (_hasEnded)
{
endOccurs(this);
}
}
}
public String output { get; set; }
public BatchExecution(String batFile)
{
batch = batFile;
}
private void workCompleted()
{
if (process != null)
{
process.Close();
process.Dispose();
GC.SuppressFinalize(process);
process = null;
}
output += "Batch ended'r'n";
hasEnded = true;
}
public void DoWork()
{
output = "Batch output:'r'n";
process = new Process();
process.StartInfo.CreateNoWindow = true;
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.Arguments = " /c '"" + batch + "'"";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.ErrorDataReceived += process_ErrorDataReceived;
process.OutputDataReceived += process_OutputDataReceived;
process.Start();
process.BeginOutputReadLine();
process.WaitForExit();
workCompleted();
}
private void process_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
output += "" + e.Data + "'r'n";
}
private void process_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
output += "" + e.Data + "'r'n";
}
}
}
从肯尼斯的建议开始,我删除了"进程。WaitForExit()"。现在使用后台工作者,我可以检查批处理执行是否完成。它似乎解决了,但我不太喜欢它。有人有更好的主意吗?
所以新版本的 Form1 代码是:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Sample
{
public partial class Form1 : Form
{
/*
* Batch files
*
c:'batch1.bat
echo startExecution
start /b calc.exe
ping 1.1.1.1 -n 1 -w 10000
echo endExecution
exit
*
*
c:'batch2.bat
echo startExecution2
start /b notepad.exe
echo endExecution2
exit
*/
private List<String> batchFiles { get; set; }
private Int32 batchIndex { get; set; }
private BatchExecution be { get; set; }
public Form1()
{
//Just for sample is unsafe
Control.CheckForIllegalCrossThreadCalls = false;
InitializeComponent();
this.button1.Click += button1_Click;
}
private void button1_Click(object sender, EventArgs e)
{
batchIndex = 0;
batchFiles = new List<String>();
batchFiles.Add("c:''batch1.bat");
batchFiles.Add("c:''batch2.bat");
this.richTextBox1.Text = "Initialized'r'n";
be = new BatchExecution(batchFiles[batchIndex]);
be.endOccurs += be_endOccurs;
be.DoWork();
}
private void be_endOccurs(BatchExecution sender)
{
this.richTextBox1.AppendText(sender.output);
if (sender.process != null)
{
sender.process.Close();
sender.process.Dispose();
GC.SuppressFinalize(sender.process);
sender.process = null;
}
sender = null;
batchIndex++;
if (batchFiles != null && batchFiles.Count > batchIndex)
{
be = new BatchExecution(batchFiles[batchIndex]);
be.endOccurs += be_endOccurs;
be.DoWork();
}
}
}
public class BatchExecution
{
private String batch { get; set; }
public Process process { get; set; }
private BackgroundWorker asyncVerifier { get; set; }
public delegate void workHasEndedHandler(BatchExecution sender);
public event workHasEndedHandler endOccurs;
private Boolean _hasEnded = false;
public Boolean hasEnded
{
get
{
return _hasEnded;
}
private set
{
_hasEnded = value;
if (_hasEnded)
{
if (asyncVerifier != null)
{
asyncVerifier.Dispose();
GC.SuppressFinalize(asyncVerifier);
asyncVerifier = null;
output += "Batch ended'r'n";
}
endOccurs(this);
}
}
}
public String output { get; set; }
public BatchExecution(String batFile)
{
batch = batFile;
}
public void DoWork()
{
output = "Batch output:'r'n";
asyncVerifier = new BackgroundWorker();
asyncVerifier.DoWork += asyncVerifier_DoWork;
process = new Process();
process.StartInfo.CreateNoWindow = true;
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.Arguments = " /c '"" + batch + "'"";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.ErrorDataReceived += process_DataReceived;
process.OutputDataReceived += process_DataReceived;
process.Start();
asyncVerifier.RunWorkerAsync();
process.BeginOutputReadLine();
}
private void asyncVerifier_DoWork(object sender, DoWorkEventArgs e)
{
Boolean performCheck = true;
while (performCheck)
{
if (process != null && !process.HasExited)
{
System.Threading.Thread.Sleep(500);
}
else
{
performCheck = false;
}
}
hasEnded = true;
}
private void process_DataReceived(object sender, DataReceivedEventArgs e)
{
output += "" + e.Data + "'r'n";
}
}
}
尝试在单独的线程中执行每个文件。这样,它们就彼此独立。
例:
class MyThreadData
{
// bat info
};
void ThreadFunction(object arg)
{
MyThreadData batInfo = (MyThreadData)arg;
// do work
}
void ExecBats(void)
{
System.Threading.Thread t1 = new System.Threading.Thread(ThreadFunction);
MyThreadData bat1 = new MyThreadData();
t1.Start(bat1);
// ...
}
如果删除对process.WaitForExit();
的调用,程序将继续,而不是等到进程退出。
显然,您对WorkCompleted
的调用不仅仅是意味着所有批次都已启动。