4 using System.Collections;
5 using System.Collections.Generic;
6 using System.Diagnostics;
8 namespace Microsoft.Build.Utilities
10 internal static class ProcessService {
11 static Dictionary<string, string> globalEnvironmentVariablesOverride;
13 public static Dictionary<string, string> GlobalEnvironmentVariblesOverride {
15 if (globalEnvironmentVariablesOverride == null)
16 globalEnvironmentVariablesOverride = new Dictionary<string, string> (StringComparer.InvariantCultureIgnoreCase);
17 return globalEnvironmentVariablesOverride;
21 public static ProcessWrapper StartProcess (string command, string arguments, string workingDirectory, EventHandler exited)
23 return StartProcess (command, arguments, workingDirectory, (ProcessEventHandler)null, (ProcessEventHandler)null, exited);
26 public static ProcessWrapper StartProcess (string command, string arguments, string workingDirectory, ProcessEventHandler outputStreamChanged, ProcessEventHandler errorStreamChanged)
28 return StartProcess (command, arguments, workingDirectory, outputStreamChanged, errorStreamChanged, null);
31 public static ProcessWrapper StartProcess (string command, string arguments, string workingDirectory, TextWriter outWriter, TextWriter errorWriter, EventHandler exited)
33 return StartProcess (command, arguments, workingDirectory, outWriter, errorWriter, exited, false);
36 public static ProcessWrapper StartProcess (string command, string arguments, string workingDirectory, TextWriter outWriter, TextWriter errorWriter, EventHandler exited, bool redirectStandardInput)
38 ProcessEventHandler wout = OutWriter.GetWriteHandler (outWriter);
39 ProcessEventHandler werr = OutWriter.GetWriteHandler (errorWriter);
40 return StartProcess (command, arguments, workingDirectory, wout, werr, exited, redirectStandardInput);
43 public static ProcessWrapper StartProcess (string command, string arguments, string workingDirectory, ProcessEventHandler outputStreamChanged, ProcessEventHandler errorStreamChanged, EventHandler exited)
45 return StartProcess (command, arguments, workingDirectory, outputStreamChanged, errorStreamChanged, exited, false);
48 public static ProcessWrapper StartProcess (string command, string arguments, string workingDirectory, ProcessEventHandler outputStreamChanged, ProcessEventHandler errorStreamChanged, EventHandler exited, bool redirectStandardInput)
50 return StartProcess (CreateProcessStartInfo (command, arguments, workingDirectory, redirectStandardInput),
51 outputStreamChanged, errorStreamChanged, exited, null);
54 public static ProcessWrapper StartProcess (ProcessStartInfo startInfo, TextWriter outWriter, TextWriter errorWriter, EventHandler exited)
56 return StartProcess (startInfo, outWriter, errorWriter, exited, null);
59 public static ProcessWrapper StartProcess (ProcessStartInfo startInfo, TextWriter outWriter, TextWriter errorWriter, EventHandler exited, Dictionary<string, string> environmentOverride)
61 ProcessEventHandler wout = OutWriter.GetWriteHandler (outWriter);
62 ProcessEventHandler werr = OutWriter.GetWriteHandler (errorWriter);
63 return StartProcess (startInfo, wout, werr, exited, environmentOverride);
66 // @environmentOverride overrides even the global override values
67 public static ProcessWrapper StartProcess (ProcessStartInfo startInfo, ProcessEventHandler outputStreamChanged, ProcessEventHandler errorStreamChanged, EventHandler exited, Dictionary<string, string> environmentOverride)
69 if (startInfo == null)
70 throw new ArgumentException ("startInfo");
72 ProcessWrapper p = new ProcessWrapper();
74 if (outputStreamChanged != null) {
75 p.OutputStreamChanged += outputStreamChanged;
78 if (errorStreamChanged != null)
79 p.ErrorStreamChanged += errorStreamChanged;
84 p.StartInfo = startInfo;
85 ProcessEnvironmentVariableOverrides (p.StartInfo, environmentOverride);
87 // WORKAROUND for "Bug 410743 - wapi leak in System.Diagnostic.Process"
88 // Process leaks when an exit event is registered
89 // instead we use another thread to monitor I/O and wait for exit
90 // p.EnableRaisingEvents = true;
96 public static ProcessStartInfo CreateProcessStartInfo (string command, string arguments, string workingDirectory, bool redirectStandardInput)
99 throw new ArgumentNullException("command");
101 if (command.Length == 0)
102 throw new ArgumentException("command");
104 ProcessStartInfo startInfo = null;
105 if(String.IsNullOrEmpty (arguments))
106 startInfo = new ProcessStartInfo (command);
108 startInfo = new ProcessStartInfo (command, arguments);
110 if(workingDirectory != null && workingDirectory.Length > 0)
111 startInfo.WorkingDirectory = workingDirectory;
113 startInfo.RedirectStandardOutput = true;
114 startInfo.RedirectStandardError = true;
115 startInfo.RedirectStandardInput = redirectStandardInput;
116 startInfo.UseShellExecute = false;
117 startInfo.CreateNoWindow = true;
122 public static void ProcessEnvironmentVariableOverrides (ProcessStartInfo info, Dictionary<string, string> environmentOverride)
124 if (globalEnvironmentVariablesOverride != null)
125 foreach (var entry in globalEnvironmentVariablesOverride)
126 ProcessEnvironmentVariable (info, (string)entry.Key, (string)entry.Value);
128 if (environmentOverride != null)
129 foreach (var entry in environmentOverride)
130 ProcessEnvironmentVariable (info, (string)entry.Key, (string)entry.Value);
133 static void ProcessEnvironmentVariable (ProcessStartInfo info, string name, string value)
135 if (value == null && info.EnvironmentVariables.ContainsKey (name))
136 info.EnvironmentVariables.Remove (name);
138 info.EnvironmentVariables[name] = value;
147 public OutWriter (TextWriter writer)
149 this.writer = writer;
152 public void WriteOut (object sender, string s)
157 public static ProcessEventHandler GetWriteHandler (TextWriter tw)
159 return tw != null ? new ProcessEventHandler(new OutWriter (tw).WriteOut) : null;