我需要使用“c#windows form application”执行多个批处理文件。如果bat包含一行或多行如:“start filename.exe”我的程序会一直等到“filename.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";
}
}
}
从Kenneth的建议开始,我删除了“process.WaitForExit()”。现在使用BackgroundWorker我可以检查批量执行是否完成。它似乎已经解决但我不太喜欢它。有人有更好的主意吗?
所以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";
}
}
}
答案 0 :(得分:1)
尝试在单独的线程中执行每个文件。 这样,他们彼此独立。
示例:
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);
// ...
}
答案 1 :(得分:0)
如果您取消对process.WaitForExit();
的调用,程序将继续,而不是等到该过程退出。
显然,您对WorkCompleted
的呼吁不仅仅意味着所有批次都已启动。