1 // created on 12/18/2004 at 16:28
3 using System.Threading;
4 using System.Diagnostics;
6 namespace Microsoft.Build.Utilities
8 internal delegate void ProcessEventHandler(object sender, string message);
10 internal class ProcessWrapper : Process, IProcessAsyncOperation
12 ManualResetEvent endEventOut = new ManualResetEvent (false);
13 ManualResetEvent endEventErr = new ManualResetEvent (false);
14 ManualResetEvent endEventExit = new ManualResetEvent (false);
17 object lockObj = new object ();
19 public ProcessWrapper ()
23 public new void Start ()
27 base.EnableRaisingEvents = true;
29 base.Exited += (s, args) => {
32 WaitHandle.WaitAll (new WaitHandle[] { endEventOut, endEventErr });
33 } catch (ObjectDisposedException) {
34 return; // we already called Dispose
37 OnExited (this, EventArgs.Empty);
40 base.OutputDataReceived += (s, args) => {
41 if (args.Data == null) {
44 } catch (ObjectDisposedException) {
45 return; // we already called Dispose
48 ProcessEventHandler handler = OutputStreamChanged;
50 handler (this, args.Data + Environment.NewLine);
54 base.ErrorDataReceived += (s, args) => {
55 if (args.Data == null) {
58 } catch (ObjectDisposedException) {
59 return; // we already called Dispose
62 ProcessEventHandler handler = ErrorStreamChanged;
64 handler (this, args.Data + Environment.NewLine);
70 base.BeginOutputReadLine ();
71 base.BeginErrorReadLine ();
74 public void WaitForOutput (int milliseconds)
77 WaitHandle.WaitAll (new WaitHandle[] { endEventOut, endEventErr, endEventExit }, milliseconds);
80 public void WaitForOutput ()
85 protected override void Dispose (bool disposing)
91 ((IAsyncOperation)this).Cancel ();
93 // if we race with base.Exited, we don't want to hang on WaitAll (endEventOut, endEventErr)
99 endEventExit.Close ();
103 base.Dispose (disposing);
106 void CheckDisposed ()
109 throw new ObjectDisposedException ("ProcessWrapper");
112 int IProcessAsyncOperation.ExitCode {
113 get { return ExitCode; }
116 int IProcessAsyncOperation.ProcessId {
120 void IAsyncOperation.Cancel ()
130 base.CancelOutputRead ();
131 } catch (InvalidOperationException) {
132 // Ignore: might happen if Start wasn't called
135 base.CancelErrorRead ();
136 } catch (InvalidOperationException) {
137 // Ignore: might happen if Start wasn't called
140 } catch (Exception ex) {
142 Console.WriteLine (ex.ToString ());
143 //LoggingService.LogError (ex.ToString ());
147 void IAsyncOperation.WaitForCompleted ()
152 void OnExited (object sender, EventArgs args)
157 OperationHandler handler = completedEvent;
166 event OperationHandler IAsyncOperation.Completed {
168 bool raiseNow = false;
173 completedEvent += value;
180 completedEvent -= value;
185 bool IAsyncOperation.Success {
186 get { return done ? ExitCode == 0 : false; }
189 bool IAsyncOperation.SuccessWithWarnings {
190 get { return false; }
193 bool IAsyncOperation.IsCompleted {
197 event OperationHandler completedEvent;
199 public event ProcessEventHandler OutputStreamChanged;
200 public event ProcessEventHandler ErrorStreamChanged;