/src/sys/dotnet/fan/sys/Process.cs
C# | 254 lines | 182 code | 37 blank | 35 comment | 35 complexity | 50d6fa38c68484b79da07f8fc0eb6628 MD5 | raw file
Possible License(s): CC-BY-SA-3.0
- //
- // Copyright (c) 2008, Brian Frank and Andy Frank
- // Licensed under the Academic Free License version 3.0
- //
- // History:
- // 6 Feb 08 Andy Frank Creation
- //
- using System;
- using System.Collections;
- using System.Text;
- namespace Fan.Sys
- {
- /// <summary>
- /// Process
- /// </summary>
- public class Process : FanObj
- {
- //////////////////////////////////////////////////////////////////////////
- // Construction
- //////////////////////////////////////////////////////////////////////////
- public static Process make()
- {
- return new Process(new List(Sys.StrType), null);
- }
- public static Process make(List command)
- {
- return new Process(command, null);
- }
- public static Process make(List command, File dir)
- {
- return new Process(command, dir);
- }
- private Process(List command, File dir)
- {
- this.command(command);
- this.dir(dir);
- }
- //////////////////////////////////////////////////////////////////////////
- // Identity
- //////////////////////////////////////////////////////////////////////////
- public override Type @typeof()
- {
- return Sys.ProcessType;
- }
- //////////////////////////////////////////////////////////////////////////
- // Configuration
- //////////////////////////////////////////////////////////////////////////
- public List command() { return m_command; }
- public void command(List v) { this.m_command = v; }
- public File dir() { return m_dir; }
- public void dir(File v)
- {
- checkRun();
- if (v != null && (!v.exists() || !v.isDir()))
- throw ArgErr.make("Invalid working directory: " + v).val;
- this.m_dir = v;
- }
- public Map env()
- {
- if (m_env == null)
- {
- m_env = new Map(Sys.StrType, Sys.StrType);
- IDictionaryEnumerator en =
- (IDictionaryEnumerator)new System.Diagnostics.Process().
- StartInfo.EnvironmentVariables.GetEnumerator();
- while (en.MoveNext())
- {
- string key = (string)en.Key;
- string val = (string)en.Value;
- m_env.set(key, val);
- }
- }
- return m_env;
- }
- public bool mergeErr() { return m_mergeErr; }
- public void mergeErr(bool v) { checkRun(); m_mergeErr = v; }
- public OutStream @out() { return m_out; }
- public void @out(OutStream @out) { checkRun(); this.m_out = @out; }
- public OutStream err() { return m_err; }
- public void err(OutStream err) { checkRun(); this.m_err = err; }
- public InStream @in() { return m_in; }
- public void @in(InStream @in) { checkRun(); this.m_in = @in; }
- //////////////////////////////////////////////////////////////////////////
- // Lifecycle
- //////////////////////////////////////////////////////////////////////////
- public Process run()
- {
- checkRun();
- try
- {
- // arguments
- string fileName = m_command.get(0) as string;
- StringBuilder args = new StringBuilder();
- for (int i=1; i<m_command.sz(); i++)
- {
- if (i > 1) args.Append(" ");
- args.Append(m_command.get(i) as string);
- }
- // create process
- m_proc = new System.Diagnostics.Process();
- m_proc.StartInfo.UseShellExecute = false;
- m_proc.StartInfo.FileName = fileName;
- m_proc.StartInfo.Arguments = args.ToString();
- // environment
- if (m_env != null)
- {
- IDictionaryEnumerator en = m_env.pairsIterator();
- while (en.MoveNext())
- {
- string key = (string)en.Key;
- string val = (string)en.Value;
- m_proc.StartInfo.EnvironmentVariables[key] = val;
- }
- }
- // working directory
- if (m_dir != null)
- m_proc.StartInfo.WorkingDirectory = ((LocalFile)m_dir).m_file.FullName;
- // streams
- if (m_in != null) m_proc.StartInfo.RedirectStandardInput = true;
- m_proc.StartInfo.RedirectStandardOutput = true;
- m_proc.StartInfo.RedirectStandardError = true;
- m_proc.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler(outHandler);
- m_proc.ErrorDataReceived += new System.Diagnostics.DataReceivedEventHandler(errHandler);
- // start it
- m_proc.Start();
- // start async read/writes
- if (m_in != null)
- {
- new System.Threading.Thread(
- new System.Threading.ThreadStart(inHandler)).Start();
- }
- m_proc.BeginOutputReadLine();
- m_proc.BeginErrorReadLine();
- return this;
- }
- catch (System.Exception e)
- {
- m_proc = null;
- throw Err.make(e).val;
- }
- }
- public long join()
- {
- if (m_proc == null) throw Err.make("Process not running").val;
- try
- {
- m_proc.WaitForExit();
- return m_proc.ExitCode;
- }
- catch (System.Exception e)
- {
- throw Err.make(e).val;
- }
- }
- public Process kill()
- {
- if (m_proc == null) throw Err.make("Process not running").val;
- m_proc.Kill();
- return this;
- }
- private void checkRun()
- {
- if (m_proc != null) throw Err.make("Process already run").val;
- }
- //////////////////////////////////////////////////////////////////////////
- // Handlers
- //////////////////////////////////////////////////////////////////////////
- private void inHandler()
- {
- System.IO.Stream input = SysInStream.dotnet(m_in);
- System.IO.Stream output = m_proc.StandardInput.BaseStream;
- byte[] temp = new byte[256];
- while (!m_proc.HasExited)
- {
- try
- {
- int n = input.Read(temp, 0, temp.Length);
- if (n < 0) break;
- output.Write(temp, 0, n);
- output.Flush();
- }
- catch (System.Exception e)
- {
- Err.dumpStack(e);
- }
- }
- }
- private void outHandler(object sender, System.Diagnostics.DataReceivedEventArgs args)
- {
- if (String.IsNullOrEmpty(args.Data)) return;
- if (m_out != null) m_out.printLine(args.Data);
- }
- private void errHandler(object sender, System.Diagnostics.DataReceivedEventArgs args)
- {
- if (String.IsNullOrEmpty(args.Data)) return;
- if (m_mergeErr)
- {
- if (m_out != null) m_out.printLine(args.Data);
- }
- else
- {
- if (m_err != null) m_err.printLine(args.Data);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- // Fields
- //////////////////////////////////////////////////////////////////////////
- private List m_command;
- private File m_dir;
- private Map m_env;
- private bool m_mergeErr = true;
- private OutStream m_out = Env.cur().@out();
- private OutStream m_err = Env.cur().err();
- private InStream m_in = null;
- private volatile System.Diagnostics.Process m_proc;
- }
- }