如何在 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";
        }
    }
}

如何在 C# 中执行多个.BAT文件

尝试在单独的线程中执行每个文件。这样,它们就彼此独立。

例:

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的调用不仅仅是意味着所有批次都已启动。