Skip to content

Instantly share code, notes, and snippets.

@Filarius
Last active April 4, 2017 09:32
Show Gist options
  • Save Filarius/71fb73c32aca2aef82271d30c94f5202 to your computer and use it in GitHub Desktop.
Save Filarius/71fb73c32aca2aef82271d30c94f5202 to your computer and use it in GitHub Desktop.
C# Console Apps Wrapper
using System;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.Threading;
namespace Helper
{
class Wrapper
{
public Process _proc;
private ProcessStartInfo _procInfo;
public MemoryStream _readStream;
public MemoryStream _errorStream;
public MemoryStream _writeStream;
public Boolean IgnoreInput;
private Thread _tread, _twrite, _terror;
private Object rLocker, wLocker, eLocker;
private bool _isRun;
private int _charBlock = 1024000 / sizeof(char);
private int _byteBlock = 1024000;
public Wrapper(string Path, string args)
{
IgnoreInput = false;
rLocker = new Object();
eLocker = new Object();
wLocker = new Object();
_errorStream = new MemoryStream(_byteBlock * 2);
_readStream = new MemoryStream(_byteBlock * 2);
_writeStream = new MemoryStream(_byteBlock * 2);
_procInfo = new ProcessStartInfo(Path, args);
_procInfo.CreateNoWindow = true;
_procInfo.UseShellExecute = false;
_procInfo.RedirectStandardError = true;
_procInfo.RedirectStandardInput = true;
_procInfo.RedirectStandardOutput = true;
_proc = new Process();
_proc.StartInfo = _procInfo;
_isRun = false;
}
~Wrapper()
{
Stop();
}
public void Start()
{
if (_isRun) return;
_isRun = true;
_proc.Start();
_proc.PriorityClass = ProcessPriorityClass.BelowNormal;
// low CPU solution to check if process is alive
(new Thread(
() =>
{
while (true)
{
try
{
if (_proc.HasExited) // HasExited is expensive operation !
{
_isRun = false;
break;
}
}
catch
{
_isRun = false;
break;
};
Wait(1000);
}
}
)
).Start();
_twrite = new Thread(
() =>
{
IntractBytes(_writeStream, _proc.StandardInput.BaseStream, wLocker);
}
);
_twrite.Start();
_tread = new Thread(
() =>
{
ExtractBytes(_proc.StandardOutput.BaseStream, _readStream, rLocker);
}
);
_tread.Start();
_terror = new Thread(
() =>
{
ExtractBytes(_proc.StandardError.BaseStream, _errorStream, eLocker);
}
);
_terror.Start();
}
public void Stop()
{
(new Thread(() =>
{
if (_isRun)
{
_isRun = false;
}
try { _tread.Abort(); } catch { }
try { _terror.Abort(); } catch { }
try { _twrite.Abort(); } catch { }
try
{
if (!_proc.HasExited)
{
Console.WriteLine("Killing " + _proc.ProcessName);
_proc.Kill();
_proc.Close();
}
}
catch
{ }
_readStream.Close();
_errorStream.Close();
_writeStream.Close();
})
).Start();
}
public void Wait()
{
System.Threading.Thread.Sleep(1);
}
public void Wait(int ms)
{
System.Threading.Thread.Sleep(ms);
}
/*
private void WaitFor(ref bool flag)
{
System.Threading.Thread.Sleep(1);
while (flag)
{
System.Threading.Thread.Sleep(1);
}
}
*/
private string BArrToString(byte[] data)
{
string reply = "";
if (data != null)
{
reply = System.Text.Encoding.ASCII.GetString(data);
}
return reply;
}
private byte[] BArrFromString(String data)
{
return Encoding.ASCII.GetBytes(data);
}
private void ExtractBytes(Stream input, Stream output, Object locker)
{
while (IsRunning)
{
if (output.Position < _byteBlock)
{
byte[] buf = new byte[_byteBlock];
int i = 0;
try
{
i = input.Read(buf, 0, _byteBlock);
}
catch
{
break;
}
if (i > 0)
{
lock (locker)
{
output.Write(buf, 0, i);
}
}
}
}
}
private void IntractBytes(Stream input, Stream output, Object locker)
{
while (IsRunning)
{
if (input.Position == 0)
{
Wait(100);
continue;
}
byte[] buf;
int pos;
lock (locker)
{
pos = (int)input.Position;
buf = new byte[pos];
input.Position = 0;
int i = input.Read(buf, 0, pos);
input.Position = 0;
}
try
{
output.Write(buf, 0, pos);
output.Flush();
}
catch
{
break;
}
}
}
public void WriteString(String data)
{
throw new Exception("Not Implemented");
}
private byte[] GetStreamData(MemoryStream stream)
{
if (stream.Position > 0)
{
int pos = (int)stream.Position;
byte[] data = new byte[pos];
stream.Position = 0;
int i = stream.Read(data, 0, pos);
if (i < stream.Position)
{
throw new Exception("Somewhy stream readed not at full length");
}
stream.Position = 0;
return data;
}
return null;
}
private void SetStreamData(MemoryStream stream, byte[] data)
{
int i = 0;
while ((i + 1) < data.Length)
{
int len = (_byteBlock * 2) - (int)stream.Position - 1;
if (len <= 0)
{
continue;
}
int cnt = data.Length - i - 1;
if (len > cnt)
{
len = cnt;
}
len = len + 1;
byte[] buf = new byte[len];
Buffer.BlockCopy(data, i, buf, 0, len);
i += len;
lock (wLocker)
{
stream.Write(buf, 0, buf.Length);
}
}
}
public byte[] Read()
{
lock (rLocker)
{
return GetStreamData(_readStream);
}
}
public string ReadString()
{
if (Monitor.TryEnter(rLocker))
{
return BArrToString(Read());
}
else
{
return "";
};
}
public byte[] Error()
{
lock (eLocker)
{
return GetStreamData(_errorStream);
}
}
public string ErrorString()
{
if (Monitor.TryEnter(eLocker, 1000))
{
try
{
return BArrToString(Error());
}
catch
{
return "";
}
finally
{
Monitor.Exit(eLocker);
}
}
else
{
return "";
}
/*
if (Monitor.TryEnter(eLocker))
{
return BArrToString(Error());
}
else
{
return "";
}
*/
}
public void Write(byte[] data)
{
SetStreamData(_writeStream, data);
}
public void Write(String data)
{
Write(BArrFromString(data));
}
public void WriteFlush()
{
_proc.StandardInput.BaseStream.Flush();
}
public Boolean IsRunning
{
get
{
try
{
//return (!_proc.HasExited); // operataion is too heavy !!
return _isRun;
}
catch
{
return false;
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment