Skip to content

Instantly share code, notes, and snippets.

@rostreim
Last active August 29, 2015 13:59
Show Gist options
  • Select an option

  • Save rostreim/10558496 to your computer and use it in GitHub Desktop.

Select an option

Save rostreim/10558496 to your computer and use it in GitHub Desktop.
A WinForm Console Shell Control
//
// Copyright 2014, Desert Software Solutions Inc.
// CommandShellControl.cs: https://gist.github.com/rostreim/10558496
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
namespace DesertSoftware.ShellControl
{
/// <summary>
/// The console event handler is used for console events.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="args">The <see cref="ConsoleEventArgs"/> instance containing the event data.</param>
public delegate void ConsoleEventHandler(object sender, ConsoleEventArgs args);
/// <summary>
/// The Command Shell Control allows you to embed a basic console in your application.
/// </summary>
[ToolboxBitmap(typeof(Resfinder), "ConsoleControl.ConsoleControl.bmp")]
public partial class CommandShellControl : UserControl
{
/// <summary>
/// Initializes a new instance of the <see cref="CommandShellControl"/> class.
/// </summary>
public CommandShellControl() {
// Initialise the component.
InitializeComponent();
// Show diagnostics disabled by default.
ShowDiagnostics = false;
// Input enabled by default.
AllowInput = true;
// Handle process events.
processManager.OnProcessOutput += processInterace_OnProcessOutput;
processManager.OnProcessError += processInterace_OnProcessError;
processManager.OnProcessInput += processInterace_OnProcessInput;
processManager.OnProcessExit += processInterace_OnProcessExit;
// Wait for key down messages on the rich text box.
richTextBoxConsole.KeyDown += richTextBoxConsole_KeyDown;
}
/// <summary>
/// Handles the OnProcessError event of the processInterace control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="args">The <see cref="ProcessEventArgs"/> instance containing the event data.</param>
void processInterace_OnProcessError(object sender, ProcessEventArgs args) {
// Write the output, in red
WriteOutput(args.Content, Color.Red);
// Fire the output event.
FireConsoleOutputEvent(args.Content);
}
/// <summary>
/// Handles the OnProcessOutput event of the processInterace control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="args">The <see cref="ProcessEventArgs"/> instance containing the event data.</param>
void processInterace_OnProcessOutput(object sender, ProcessEventArgs args) {
// Write the output, in white
WriteOutput(args.Content, Color.White);
// Fire the output event.
FireConsoleOutputEvent(args.Content);
}
/// <summary>
/// Handles the OnProcessInput event of the processInterace control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="args">The <see cref="ProcessEventArgs"/> instance containing the event data.</param>
void processInterace_OnProcessInput(object sender, ProcessEventArgs args) {
throw new NotImplementedException();
}
/// <summary>
/// Handles the OnProcessExit event of the processInterace control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="args">The <see cref="ProcessEventArgs"/> instance containing the event data.</param>
void processInterace_OnProcessExit(object sender, ProcessEventArgs args) {
// Are we showing diagnostics?
if (ShowDiagnostics) {
WriteOutput(Environment.NewLine + processManager.ProcessFileName + " exited.", Color.FromArgb(255, 0, 255, 0));
}
if (!this.IsHandleCreated)
return;
// Read only again.
Invoke((Action)(() => {
richTextBoxConsole.ReadOnly = true;
}));
}
///// <summary>
///// Initialises the key mappings.
///// </summary>
//private void InitialiseKeyMappings()
//{
// // Map 'tab'.
// keyMappings.Add(new KeyMapping(false, false, false, Keys.Tab, "{TAB}", "\t"));
// // Map 'Ctrl-C'.
// keyMappings.Add(new KeyMapping(true, false, false, Keys.C, "^(c)", "\x03\r\n"));
//}
/// <summary>
/// Handles the KeyDown event of the richTextBoxConsole control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.Windows.Forms.KeyEventArgs"/> instance containing the event data.</param>
void richTextBoxConsole_KeyDown(object sender, KeyEventArgs e) {
// If we're at the input point and it's backspace, bail.
if ((richTextBoxConsole.SelectionStart <= inputStart) && e.KeyCode == Keys.Back) e.SuppressKeyPress = true;
// Are we in the read-only zone?
if (richTextBoxConsole.SelectionStart < inputStart) {
// Allow arrows, control, shift
if (!(e.KeyCode == Keys.Left || e.KeyCode == Keys.ShiftKey || e.KeyCode == Keys.ControlKey ||
e.KeyCode == Keys.Right || e.KeyCode == Keys.Up || e.KeyCode == Keys.Down)) {
richTextBoxConsole.SelectionStart = richTextBoxConsole.TextLength;
}
}
if (e.KeyCode == Keys.K && e.Control) {
WriteInput("\x03\r\n", Color.WhiteSmoke, false);
}
// Is it the return key?
if (e.KeyCode == Keys.Return) {
// Get the input.
string input = richTextBoxConsole.Text.Substring(inputStart, richTextBoxConsole.TextLength - inputStart);
// (richTextBoxConsole.SelectionStart) - inputStart);
// Write the input (without echoing).
WriteInput(input, Color.White, false);
}
}
/// <summary>
/// Writes the output to the console control.
/// </summary>
/// <param name="output">The output.</param>
/// <param name="color">The color.</param>
public void WriteOutput(string output, Color color) {
if (string.IsNullOrEmpty(lastInput) == false &&
(output == lastInput || output.Replace("\r\n", "") == lastInput))
return;
if (!this.IsHandleCreated)
return;
Invoke((Action)(() => {
// Write the output.
richTextBoxConsole.SelectionColor = color;
richTextBoxConsole.SelectedText += output;
inputStart = richTextBoxConsole.SelectionStart;
}));
}
/// <summary>
/// Clears the output.
/// </summary>
public void ClearOutput() {
richTextBoxConsole.Clear();
inputStart = 0;
}
/// <summary>
/// Writes the line of input to the console control.
/// </summary>
/// <param name="input">The input.</param>
/// <param name="color">The color.</param>
/// <param name="echo">if set to <c>true</c> echo the input.</param>
public void WriteInput(string input, Color color, bool echo) {
Invoke((Action)(() => {
// Are we echoing?
if (echo) {
if (richTextBoxConsole.SelectionStart < inputStart)
richTextBoxConsole.SelectionStart = richTextBoxConsole.TextLength;
richTextBoxConsole.SelectionColor = color;
richTextBoxConsole.SelectedText += input + "\n";
inputStart = richTextBoxConsole.SelectionStart;
}
lastInput = input;
// Write the input.
processManager.WriteInput(input);
// Fire the event.
FireConsoleInputEvent(input);
}));
}
/// <summary>
/// Runs a process.
/// </summary>
/// <param name="fileName">Name of the file.</param>
/// <param name="arguments">The arguments.</param>
public void StartProcess(string fileName, string arguments) {
// Are we showing diagnostics?
if (ShowDiagnostics) {
WriteOutput("Preparing to run " + fileName, Color.FromArgb(255, 0, 255, 0));
if (!string.IsNullOrEmpty(arguments))
WriteOutput(" with arguments " + arguments + "." + Environment.NewLine, Color.FromArgb(255, 0, 255, 0));
else
WriteOutput("." + Environment.NewLine, Color.FromArgb(255, 0, 255, 0));
}
// Start the process.
processManager.StartProcess(fileName, arguments);
// If we enable input, make the control not read only.
if (this.allowInput)
richTextBoxConsole.ReadOnly = false;
}
/// <summary>
/// Stops the process.
/// </summary>
public void StopProcess() {
// Stop the interface.
processManager.StopProcess();
}
/// <summary>
/// Fires the console output event.
/// </summary>
/// <param name="content">The content.</param>
private void FireConsoleOutputEvent(string content) {
// Get the event.
var theEvent = OnConsoleOutput;
if (theEvent != null)
theEvent(this, new ConsoleEventArgs(content));
}
/// <summary>
/// Fires the console input event.
/// </summary>
/// <param name="content">The content.</param>
private void FireConsoleInputEvent(string content) {
// Get the event.
var theEvent = OnConsoleInput;
if (theEvent != null)
theEvent(this, new ConsoleEventArgs(content));
}
/// <summary>
/// The internal process interface used to interface with the process.
/// </summary>
private readonly ProcessManager processManager = new ProcessManager();
/// <summary>
/// Current position that input starts at.
/// </summary>
int inputStart = -1;
/// <summary>
/// The is input enabled flag.
/// </summary>
private bool allowInput = true;
/// <summary>
/// The last input string (used so that we can make sure we don't echo input twice).
/// </summary>
private string lastInput;
///// <summary>
///// The key mappings.
///// </summary>
//private List<KeyMapping> keyMappings = new List<KeyMapping>();
/// <summary>
/// Occurs when console output is produced.
/// </summary>
public event ConsoleEventHandler OnConsoleOutput;
/// <summary>
/// Occurs when console input is produced.
/// </summary>
public event ConsoleEventHandler OnConsoleInput;
/// <summary>
/// Gets or sets a value indicating whether to show diagnostics.
/// </summary>
/// <value>
/// <c>true</c> if show diagnostics; otherwise, <c>false</c>.
/// </value>
[Category("Console Control"), Description("Show diagnostic information, such as exceptions.")]
public bool ShowDiagnostics { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this instance is input enabled.
/// </summary>
/// <value>
/// <c>true</c> if this instance is input enabled; otherwise, <c>false</c>.
/// </value>
[Category("Console Control"), Description("If true, the user can key in input.")]
public bool AllowInput {
get { return this.allowInput; }
set {
this.allowInput = value;
if (IsProcessRunning)
richTextBoxConsole.ReadOnly = !value;
}
}
/// <summary>
/// Gets a value indicating whether this instance is process running.
/// </summary>
/// <value>
/// <c>true</c> if this instance is process running; otherwise, <c>false</c>.
/// </value>
[Browsable(false)]
public bool IsProcessRunning {
get { return processManager.IsProcessRunning; }
}
/// <summary>
/// Gets the internal rich text box.
/// </summary>
[Browsable(false)]
public RichTextBox InternalRichTextBox {
get { return richTextBoxConsole; }
}
/// <summary>
/// Gets the process interface.
/// </summary>
[Browsable(false)]
public ProcessManager ProcessInterface {
get { return processManager; }
}
///// <summary>
///// Gets the key mappings.
///// </summary>
//[Browsable(false)]
//public List<KeyMapping> KeyMappings {
// get { return keyMappings; }
//}
/// <summary>
/// Gets or sets the font of the text displayed by the control.
/// </summary>
/// <returns>The <see cref="T:System.Drawing.Font" /> to apply to the text displayed by the control. The default is the value of the <see cref="P:System.Windows.Forms.Control.DefaultFont" /> property.</returns>
/// <PermissionSet>
/// <IPermission class="System.Security.Permissions.EnvironmentPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
/// <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
/// <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="UnmanagedCode, ControlEvidence" />
/// <IPermission class="System.Diagnostics.PerformanceCounterPermission, System, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
/// </PermissionSet>
public override Font Font {
get {
// Return the base class font.
return base.Font;
}
set {
// Set the base class font...
base.Font = value;
// ...and the internal control font.
richTextBoxConsole.Font = value;
}
}
/// <summary>
/// Gets or sets the background color for the control.
/// </summary>
/// <returns>A <see cref="T:System.Drawing.Color" /> that represents the background color of the control. The default is the value of the <see cref="P:System.Windows.Forms.Control.DefaultBackColor" /> property.</returns>
/// <PermissionSet>
/// <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
/// </PermissionSet>
public override Color BackColor {
get {
// Return the base class background.
return base.BackColor;
}
set {
// Set the base class background...
base.BackColor = value;
// ...and the internal control background.
richTextBoxConsole.BackColor = value;
}
}
}
/// <summary>
/// Used to allow us to find resources properly.
/// </summary>
public class Resfinder { }
}
//
// Copyright 2014, Desert Software Solutions Inc.
// ConsoleEventArgs.cs: https://gist.github.com/rostreim/10558496
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
using System;
namespace DesertSoftware.ShellControl
{
/// <summary>
/// The ConsoleEventArgs are arguments for a console event.
/// </summary>
public class ConsoleEventArgs : EventArgs
{
/// <summary>
/// Initializes a new instance of the <see cref="ConsoleEventArgs"/> class.
/// </summary>
public ConsoleEventArgs() { }
/// <summary>
/// Initializes a new instance of the <see cref="ConsoleEventArgs"/> class.
/// </summary>
/// <param name="content">The content.</param>
public ConsoleEventArgs(string content) {
// Set the content.
Content = content;
}
/// <summary>
/// Gets the content.
/// </summary>
public string Content { get; private set; }
}
}
//
// Copyright 2014, Desert Software Solutions Inc.
// ProcessEventArgs.cs: https://gist.github.com/rostreim/10558496
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
using System;
namespace DesertSoftware.ShellControl
{
/// <summary>
/// The ProcessEventArgs are arguments for a console event.
/// </summary>
public class ProcessEventArgs : EventArgs
{
/// <summary>
/// Initializes a new instance of the <see cref="ProcessEventArgs"/> class.
/// </summary>
public ProcessEventArgs() { }
/// <summary>
/// Initializes a new instance of the <see cref="ProcessEventArgs"/> class.
/// </summary>
/// <param name="content">The content.</param>
public ProcessEventArgs(string content) {
// Set the content.
Content = content;
}
/// <summary>
/// Initializes a new instance of the <see cref="ProcessEventArgs"/> class.
/// </summary>
/// <param name="code">The code.</param>
public ProcessEventArgs(int code) {
// Set the code.
Code = code;
}
/// <summary>
/// Initializes a new instance of the <see cref="ProcessEventArgs"/> class.
/// </summary>
/// <param name="content">The content.</param>
/// <param name="code">The code.</param>
public ProcessEventArgs(string content, int code) {
// Set the content and code.
Content = content;
Code = code;
}
/// <summary>
/// Gets the content.
/// </summary>
public string Content { get; private set; }
/// <summary>
/// Gets or sets the code.
/// </summary>
/// <value>
/// The code.
/// </value>
public int? Code { get; private set; }
}
}
//
// Copyright 2014, Desert Software Solutions Inc.
// ProcessManager.cs: https://gist.github.com/rostreim/10558496
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
using System;
using System.Text;
using System.Diagnostics;
using System.ComponentModel;
using System.IO;
namespace DesertSoftware.ShellControl
{
/// <summary>
/// A ProcessEventHandler is a delegate for process input/output events.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="args">The <see cref="ProcessEventArgs"/> instance containing the event data.</param>
public delegate void ProcessEventHandler(object sender, ProcessEventArgs args);
/// <summary>
/// A class that wraps a process providing programmatic input and output.
/// </summary>
public class ProcessManager
{
/// <summary>
/// Initializes a new instance of the <see cref="ProcessManager"/> class.
/// </summary>
public ProcessManager()
{
// Configure the output worker.
outputWorker.WorkerReportsProgress = true;
outputWorker.WorkerSupportsCancellation = true;
outputWorker.DoWork += outputWorker_DoWork;
outputWorker.ProgressChanged += outputWorker_ProgressChanged;
// Configure the error worker.
errorWorker.WorkerReportsProgress = true;
errorWorker.WorkerSupportsCancellation = true;
errorWorker.DoWork += errorWorker_DoWork;
errorWorker.ProgressChanged += errorWorker_ProgressChanged;
}
/// <summary>
/// Handles the ProgressChanged event of the outputWorker control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.ComponentModel.ProgressChangedEventArgs"/> instance containing the event data.</param>
void outputWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// We must be passed a string in the user state.
if (e.UserState is string)
{
// Fire the output event.
FireProcessOutputEvent(e.UserState as string);
}
}
/// <summary>
/// Handles the DoWork event of the outputWorker control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.ComponentModel.DoWorkEventArgs"/> instance containing the event data.</param>
void outputWorker_DoWork(object sender, DoWorkEventArgs e)
{
while (outputWorker.CancellationPending == false)
{
// Any lines to read?
int count;
var buffer = new char[1024];
do
{
var builder = new StringBuilder();
count = outputReader.Read(buffer, 0, 1024);
builder.Append(buffer, 0, count);
outputWorker.ReportProgress(0, builder.ToString());
} while (count > 0);
System.Threading.Thread.Sleep(200);
}
}
/// <summary>
/// Handles the ProgressChanged event of the errorWorker control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.ComponentModel.ProgressChangedEventArgs"/> instance containing the event data.</param>
void errorWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// The userstate must be a string.
if (e.UserState is string)
{
// Fire the error event.
FireProcessErrorEvent(e.UserState as string);
}
}
/// <summary>
/// Handles the DoWork event of the errorWorker control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.ComponentModel.DoWorkEventArgs"/> instance containing the event data.</param>
void errorWorker_DoWork(object sender, DoWorkEventArgs e)
{
while (errorWorker.CancellationPending == false)
{
// Any lines to read?
int count;
var buffer = new char[1024];
do
{
var builder = new StringBuilder();
count = errorReader.Read(buffer, 0, 1024);
builder.Append(buffer, 0, count);
errorWorker.ReportProgress(0, builder.ToString());
} while (count > 0);
System.Threading.Thread.Sleep(200);
}
}
/// <summary>
/// Runs a process.
/// </summary>
/// <param name="fileName">Name of the file.</param>
/// <param name="arguments">The arguments.</param>
public void StartProcess(string fileName, string arguments)
{
// Create the process start info.
var processStartInfo = new ProcessStartInfo(fileName, arguments);
// Set the options.
processStartInfo.UseShellExecute = false;
processStartInfo.ErrorDialog = false;
processStartInfo.CreateNoWindow = true;
// Specify redirection.
processStartInfo.RedirectStandardError = true;
processStartInfo.RedirectStandardInput = true;
processStartInfo.RedirectStandardOutput = true;
// Create the process.
process = new Process();
process.EnableRaisingEvents = true;
process.StartInfo = processStartInfo;
process.Exited += currentProcess_Exited;
// Start the process.
try
{
process.Start();
}
catch (Exception e)
{
// Trace the exception.
Trace.WriteLine("Failed to start process " + fileName + " with arguments '" + arguments + "'");
Trace.WriteLine(e.ToString());
return;
}
// Store name and arguments.
processFileName = fileName;
processArguments = arguments;
// Create the readers and writers.
inputWriter = process.StandardInput;
outputReader = TextReader.Synchronized(process.StandardOutput);
errorReader = TextReader.Synchronized(process.StandardError);
// Run the workers that read output and error.
outputWorker.RunWorkerAsync();
errorWorker.RunWorkerAsync();
}
/// <summary>
/// Stops the process.
/// </summary>
public void StopProcess()
{
// Handle the trivial case.
if (IsProcessRunning == false)
return;
// Kill the process.
process.Kill();
}
/// <summary>
/// Handles the Exited event of the currentProcess control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
void currentProcess_Exited(object sender, EventArgs e)
{
// Fire process exited.
FireProcessExitEvent(process.ExitCode);
// Disable the threads.
outputWorker.CancelAsync();
errorWorker.CancelAsync();
inputWriter = null;
outputReader = null;
errorReader = null;
process = null;
processFileName = null;
processArguments = null;
}
/// <summary>
/// Fires the process output event.
/// </summary>
/// <param name="content">The content.</param>
private void FireProcessOutputEvent(string content)
{
// Get the event and fire it.
var theEvent = OnProcessOutput;
if (theEvent != null)
theEvent(this, new ProcessEventArgs(content));
}
/// <summary>
/// Fires the process error output event.
/// </summary>
/// <param name="content">The content.</param>
private void FireProcessErrorEvent(string content)
{
// Get the event and fire it.
var theEvent = OnProcessError;
if (theEvent != null)
theEvent(this, new ProcessEventArgs(content));
}
// Fires the process input event.
private void FireProcessInputEvent(string content) {
var theEvent = OnProcessInput;
if (theEvent != null)
theEvent(this, new ProcessEventArgs(content));
}
// Fires the process exit event
private void FireProcessExitEvent(int code) {
var theEvent = OnProcessExit;
if (theEvent != null)
theEvent(this, new ProcessEventArgs(code));
}
/// <summary>
/// Writes the input.
/// </summary>
/// <param name="input">The input.</param>
public void WriteInput(string input)
{
if (IsProcessRunning)
{
inputWriter.WriteLine(input);
inputWriter.Flush();
}
}
private Process process; // the current process we are managing
private StreamWriter inputWriter; // the writer to which all input is echoed to
private TextReader outputReader; // the stdout reader to which the process is writing
private TextReader errorReader; // the stderr reader to which the process is writing
private BackgroundWorker outputWorker = new BackgroundWorker();
private BackgroundWorker errorWorker = new BackgroundWorker();
private string processFileName;
private string processArguments;
/// <summary>
/// Occurs when the process writes to stdout
/// </summary>
public event ProcessEventHandler OnProcessOutput;
/// <summary>
/// Occurs when the process writes to stderr
/// </summary>
public event ProcessEventHandler OnProcessError;
/// <summary>
/// Occurs when input is received from the process.
/// </summary>
public event ProcessEventHandler OnProcessInput;
/// <summary>
/// Occurs when the process ends.
/// </summary>
public event ProcessEventHandler OnProcessExit;
/// <summary>
/// Gets a value indicating whether this instance is process running.
/// </summary>
/// <value>
/// <c>true</c> if this instance is process running; otherwise, <c>false</c>.
/// </value>
public bool IsProcessRunning {
get {
try {
return (this.process != null && !this.process.HasExited);
} catch {
return false;
}
}
}
/// <summary>
/// Gets the active process instance
/// </summary>
public Process Process {
get { return this.process; }
}
/// <summary>
/// Gets the file name of the process.
/// </summary>
public string ProcessFileName {
get { return this.processFileName; }
}
/// <summary>
/// Gets the process arguments.
/// </summary>
public string ProcessArguments
{
get { return this.processArguments; }
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment