using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.Collections;
using System.ComponentModel;
namespace System.Diagnostics.ProcessCaller
{
///
/// Delegate used by the events StdOutReceived and StdErrReceived.
///
public delegate void DataReceivedHandler(object sender, DataReceivedEventArgs e);
///
/// Event Args for above delegate
///
public class DataReceivedEventArgs : EventArgs
{
///
/// The text that was received
///
public string Text;
///
/// Constructor
///
/// The text that was received for this event to be triggered.
public DataReceivedEventArgs(string text)
{
this.Text = text;
}
}
///
/// A class to launch a process (ie. *.exe, *.bat, etc.) and
/// return the StandardOutput and StandardError lines during execution.
///
///
/// This class was based on the ProcessCaller class by Michael Mayer
/// which was released under public domain licensing.
///
public class ProcessCaller : AsyncOperation
{
///
/// The command to run (should be made into a property)
///
public string FileName;
///
/// The Arguments for the cmd (should be made into a property)
///
public string Arguments;
///
/// The WorkingDirectory (should be made into a property)
///
public string WorkingDirectory;
///
/// Fired for every line of stdOut received.
///
public event DataReceivedHandler StdOutReceived;
///
/// Fired for every line of stdErr received.
///
public event DataReceivedHandler StdErrReceived;
///
/// Amount of time to sleep on threads while waiting
/// for the process to finish.
///
public int SleepTime = 500;
///
/// The process used to run your task
///
private Process process;
///
/// Initialises a ProcessCaller with an association to the
/// supplied ISynchronizeInvoke. All events raised from this
/// object will be delivered via this target. (This might be a
/// Control object, so events would be delivered to that Control's
/// UI thread.)
///
/// An object implementing the
/// ISynchronizeInvoke interface. All events will be delivered
/// through this target, ensuring that they are delivered to the
/// correct thread.
public ProcessCaller(ISynchronizeInvoke isi) : base(isi)
{
}
///
/// Launch a process, but do not return until the process has exited.
/// That way we can kill the process if a cancel is requested.
///
protected override void DoWork()
{
this.StartProcess();
// Wait for the process to end, or cancel it
while (! process.HasExited)
{
Thread.Sleep(SleepTime); // sleep
if (this.CancelRequested)
{
// Not a very nice way to end a process,
// but effective.
process.Kill();
this.AcknowledgeCancel();
}
}
}
///
/// This method is generally called by DoWork()
/// which is called by the base classs Start()
///
protected virtual void StartProcess()
{
// Start a new process for the cmd
process = new Process();
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.FileName = FileName;
process.StartInfo.Arguments = Arguments;
process.StartInfo.WorkingDirectory = WorkingDirectory;
process.Start();
// Invoke stdOut and stdErr readers - each
// has its own thread to guarantee that they aren't
// blocked by, or cause a block to, the actual
// process running (or the gui).
new MethodInvoker(ReadStdOut).BeginInvoke(null, null);
new MethodInvoker(ReadStdErr).BeginInvoke(null, null);
}
///
/// Handles reading of stdout and firing an event for
/// every line read
///
protected virtual void ReadStdOut()
{
string line;
while ((line = process.StandardOutput.ReadLine()) != null)
this.FireAsync(StdOutReceived, this, new DataReceivedEventArgs(line));
}
///
/// Handles reading of stdErr
///
protected virtual void ReadStdErr()
{
string line;
while ((line = process.StandardError.ReadLine()) != null)
{
this.FireAsync(StdErrReceived, this, new DataReceivedEventArgs(line));
}
}
}
}