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 WaitForExit (milliseconds);
78 WaitHandle.WaitAll (new WaitHandle[] { endEventOut, endEventErr, endEventExit }, milliseconds);
81 public void WaitForOutput ()
86 protected override void Dispose (bool disposing)
92 ((IAsyncOperation)this).Cancel ();
94 // if we race with base.Exited, we don't want to hang on WaitAll (endEventOut, endEventErr)
100 endEventExit.Close ();
104 base.Dispose (disposing);
107 void CheckDisposed ()
110 throw new ObjectDisposedException ("ProcessWrapper");
113 int IProcessAsyncOperation.ExitCode {
114 get { return ExitCode; }
117 int IProcessAsyncOperation.ProcessId {
121 void IAsyncOperation.Cancel ()
131 base.CancelOutputRead ();
132 } catch (InvalidOperationException) {
133 // Ignore: might happen if Start wasn't called
136 base.CancelErrorRead ();
137 } catch (InvalidOperationException) {
138 // Ignore: might happen if Start wasn't called
141 } catch (Exception ex) {
143 Console.WriteLine (ex.ToString ());
144 //LoggingService.LogError (ex.ToString ());
148 void IAsyncOperation.WaitForCompleted ()
153 void OnExited (object sender, EventArgs args)
158 OperationHandler handler = completedEvent;
167 event OperationHandler IAsyncOperation.Completed {
169 bool raiseNow = false;
174 completedEvent += value;
181 completedEvent -= value;
186 bool IAsyncOperation.Success {
187 get { return done ? ExitCode == 0 : false; }
190 bool IAsyncOperation.SuccessWithWarnings {
191 get { return false; }
194 bool IAsyncOperation.IsCompleted {
198 event OperationHandler completedEvent;
200 public event ProcessEventHandler OutputStreamChanged;
201 public event ProcessEventHandler ErrorStreamChanged;