5 using System.Collections;
6 using System.Collections.Specialized;
7 using System.Diagnostics;
9 using SCS = System.Collections.Specialized;
11 namespace Microsoft.Build.Utilities
13 internal static class ProcessService {
14 static SCS.ProcessStringDictionary globalEnvironmentVariablesOverride;
16 public static StringDictionary GlobalEnvironmentVariblesOverride {
18 if (globalEnvironmentVariablesOverride == null)
19 globalEnvironmentVariablesOverride = new SCS.ProcessStringDictionary ();
20 return globalEnvironmentVariablesOverride;
24 public static ProcessWrapper StartProcess (string command, string arguments, string workingDirectory, EventHandler exited)
26 return StartProcess (command, arguments, workingDirectory, (ProcessEventHandler)null, (ProcessEventHandler)null, exited);
29 public static ProcessWrapper StartProcess (string command, string arguments, string workingDirectory, ProcessEventHandler outputStreamChanged, ProcessEventHandler errorStreamChanged)
31 return StartProcess (command, arguments, workingDirectory, outputStreamChanged, errorStreamChanged, null);
34 public static ProcessWrapper StartProcess (string command, string arguments, string workingDirectory, TextWriter outWriter, TextWriter errorWriter, EventHandler exited)
36 return StartProcess (command, arguments, workingDirectory, outWriter, errorWriter, exited, false);
39 public static ProcessWrapper StartProcess (string command, string arguments, string workingDirectory, TextWriter outWriter, TextWriter errorWriter, EventHandler exited, bool redirectStandardInput)
41 ProcessEventHandler wout = OutWriter.GetWriteHandler (outWriter);
42 ProcessEventHandler werr = OutWriter.GetWriteHandler (errorWriter);
43 return StartProcess (command, arguments, workingDirectory, wout, werr, exited, redirectStandardInput);
46 public static ProcessWrapper StartProcess (string command, string arguments, string workingDirectory, ProcessEventHandler outputStreamChanged, ProcessEventHandler errorStreamChanged, EventHandler exited)
48 return StartProcess (command, arguments, workingDirectory, outputStreamChanged, errorStreamChanged, exited, false);
51 public static ProcessWrapper StartProcess (string command, string arguments, string workingDirectory, ProcessEventHandler outputStreamChanged, ProcessEventHandler errorStreamChanged, EventHandler exited, bool redirectStandardInput)
53 return StartProcess (CreateProcessStartInfo (command, arguments, workingDirectory, redirectStandardInput),
54 outputStreamChanged, errorStreamChanged, exited, null);
57 public static ProcessWrapper StartProcess (ProcessStartInfo startInfo, TextWriter outWriter, TextWriter errorWriter, EventHandler exited)
59 return StartProcess (startInfo, outWriter, errorWriter, exited, null);
62 public static ProcessWrapper StartProcess (ProcessStartInfo startInfo, TextWriter outWriter, TextWriter errorWriter, EventHandler exited, StringDictionary environmentOverride)
64 ProcessEventHandler wout = OutWriter.GetWriteHandler (outWriter);
65 ProcessEventHandler werr = OutWriter.GetWriteHandler (errorWriter);
66 return StartProcess (startInfo, wout, werr, exited, environmentOverride);
69 // @environmentOverride overrides even the global override values
70 public static ProcessWrapper StartProcess (ProcessStartInfo startInfo, ProcessEventHandler outputStreamChanged, ProcessEventHandler errorStreamChanged, EventHandler exited, StringDictionary environmentOverride)
72 if (startInfo == null)
73 throw new ArgumentException ("startInfo");
75 ProcessWrapper p = new ProcessWrapper();
77 if (outputStreamChanged != null) {
78 p.OutputStreamChanged += outputStreamChanged;
81 if (errorStreamChanged != null)
82 p.ErrorStreamChanged += errorStreamChanged;
87 p.StartInfo = startInfo;
88 ProcessEnvironmentVariableOverrides (p.StartInfo, environmentOverride);
90 // WORKAROUND for "Bug 410743 - wapi leak in System.Diagnostic.Process"
91 // Process leaks when an exit event is registered
92 // instead we use another thread to monitor I/O and wait for exit
93 // p.EnableRaisingEvents = true;
99 public static ProcessStartInfo CreateProcessStartInfo (string command, string arguments, string workingDirectory, bool redirectStandardInput)
102 throw new ArgumentNullException("command");
104 if (command.Length == 0)
105 throw new ArgumentException("command");
107 ProcessStartInfo startInfo = null;
108 if(String.IsNullOrEmpty (arguments))
109 startInfo = new ProcessStartInfo (command);
111 startInfo = new ProcessStartInfo (command, arguments);
113 if(workingDirectory != null && workingDirectory.Length > 0)
114 startInfo.WorkingDirectory = workingDirectory;
116 startInfo.RedirectStandardOutput = true;
117 startInfo.RedirectStandardError = true;
118 startInfo.RedirectStandardInput = redirectStandardInput;
119 startInfo.UseShellExecute = false;
124 public static void ProcessEnvironmentVariableOverrides (ProcessStartInfo info, StringDictionary environmentOverride)
126 if (globalEnvironmentVariablesOverride != null)
127 foreach (DictionaryEntry entry in globalEnvironmentVariablesOverride)
128 ProcessEnvironmentVariable (info, (string)entry.Key, (string)entry.Value);
130 if (environmentOverride != null)
131 foreach (DictionaryEntry entry in environmentOverride)
132 ProcessEnvironmentVariable (info, (string)entry.Key, (string)entry.Value);
135 static void ProcessEnvironmentVariable (ProcessStartInfo info, string name, string value)
137 if (value == null && info.EnvironmentVariables.ContainsKey (name))
138 info.EnvironmentVariables.Remove (name);
140 info.EnvironmentVariables[name] = value;
149 public OutWriter (TextWriter writer)
151 this.writer = writer;
154 public void WriteOut (object sender, string s)
159 public static ProcessEventHandler GetWriteHandler (TextWriter tw)
161 return tw != null ? new ProcessEventHandler(new OutWriter (tw).WriteOut) : null;