Merge pull request #778 from cmorris98/master
[mono.git] / mcs / class / Microsoft.Build.Utilities / Microsoft.Build.Utilities / ProcessService.cs
1 #if NET_2_0
2
3 using System;
4 using System.IO;
5 using System.Collections;
6 using System.Collections.Specialized;
7 using System.Diagnostics;
8
9 using SCS = System.Collections.Specialized;
10
11 namespace Microsoft.Build.Utilities
12 {
13         internal static class ProcessService {
14                 static SCS.ProcessStringDictionary globalEnvironmentVariablesOverride;
15
16                 public static StringDictionary GlobalEnvironmentVariblesOverride {
17                         get {
18                                 if (globalEnvironmentVariablesOverride == null)
19                                         globalEnvironmentVariablesOverride = new SCS.ProcessStringDictionary ();
20                                 return globalEnvironmentVariablesOverride;
21                         }
22                 }
23
24                 public static ProcessWrapper StartProcess (string command, string arguments, string workingDirectory, EventHandler exited)
25                 {
26                         return StartProcess (command, arguments, workingDirectory, (ProcessEventHandler)null, (ProcessEventHandler)null, exited);
27                 }
28
29                 public static ProcessWrapper StartProcess (string command, string arguments, string workingDirectory, ProcessEventHandler outputStreamChanged, ProcessEventHandler errorStreamChanged)
30                 {
31                         return StartProcess (command, arguments, workingDirectory, outputStreamChanged, errorStreamChanged, null);
32                 }
33
34                 public static ProcessWrapper StartProcess (string command, string arguments, string workingDirectory, TextWriter outWriter, TextWriter errorWriter, EventHandler exited)
35                 {
36                         return StartProcess (command, arguments, workingDirectory, outWriter, errorWriter, exited, false);
37                 }
38
39                 public static ProcessWrapper StartProcess (string command, string arguments, string workingDirectory, TextWriter outWriter, TextWriter errorWriter, EventHandler exited, bool redirectStandardInput)
40                 {
41                         ProcessEventHandler wout = OutWriter.GetWriteHandler (outWriter);
42                         ProcessEventHandler werr = OutWriter.GetWriteHandler (errorWriter);
43                         return StartProcess (command, arguments, workingDirectory, wout, werr, exited, redirectStandardInput);
44                 }
45
46                 public static ProcessWrapper StartProcess (string command, string arguments, string workingDirectory, ProcessEventHandler outputStreamChanged, ProcessEventHandler errorStreamChanged, EventHandler exited)
47                 {
48                         return StartProcess (command, arguments, workingDirectory, outputStreamChanged, errorStreamChanged, exited, false);
49                 }
50
51                 public static ProcessWrapper StartProcess (string command, string arguments, string workingDirectory, ProcessEventHandler outputStreamChanged, ProcessEventHandler errorStreamChanged, EventHandler exited, bool redirectStandardInput)
52                 {
53                         return StartProcess (CreateProcessStartInfo (command, arguments, workingDirectory, redirectStandardInput),
54                                 outputStreamChanged, errorStreamChanged, exited, null);
55                 }
56
57                 public static ProcessWrapper StartProcess (ProcessStartInfo startInfo, TextWriter outWriter, TextWriter errorWriter, EventHandler exited)
58                 {
59                         return StartProcess (startInfo, outWriter, errorWriter, exited, null);
60                 }
61
62                 public static ProcessWrapper StartProcess (ProcessStartInfo startInfo, TextWriter outWriter, TextWriter errorWriter, EventHandler exited, StringDictionary environmentOverride)
63                 {
64                         ProcessEventHandler wout = OutWriter.GetWriteHandler (outWriter);
65                         ProcessEventHandler werr = OutWriter.GetWriteHandler (errorWriter);
66                         return StartProcess (startInfo, wout, werr, exited, environmentOverride);
67                 }
68
69                 // @environmentOverride overrides even the global override values
70                 public static ProcessWrapper StartProcess (ProcessStartInfo startInfo, ProcessEventHandler outputStreamChanged, ProcessEventHandler errorStreamChanged, EventHandler exited, StringDictionary environmentOverride)
71                 {
72                         if (startInfo == null)
73                                 throw new ArgumentException ("startInfo");
74
75                         ProcessWrapper p = new ProcessWrapper();
76
77                         if (outputStreamChanged != null) {
78                                 p.OutputStreamChanged += outputStreamChanged;
79                         }
80
81                         if (errorStreamChanged != null)
82                                 p.ErrorStreamChanged += errorStreamChanged;
83
84                         if (exited != null)
85                                 p.Exited += exited;
86
87                         p.StartInfo = startInfo;
88                         ProcessEnvironmentVariableOverrides (p.StartInfo, environmentOverride);
89
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;
94
95                         p.Start ();
96                         return p;
97                 }
98
99                 public static ProcessStartInfo CreateProcessStartInfo (string command, string arguments, string workingDirectory, bool redirectStandardInput)
100                 {
101                         if (command == null)
102                                 throw new ArgumentNullException("command");
103
104                         if (command.Length == 0)
105                                 throw new ArgumentException("command");
106
107                         ProcessStartInfo startInfo = null;
108                         if(String.IsNullOrEmpty (arguments))
109                                 startInfo = new ProcessStartInfo (command);
110                         else
111                                 startInfo = new ProcessStartInfo (command, arguments);
112
113                         if(workingDirectory != null && workingDirectory.Length > 0)
114                                 startInfo.WorkingDirectory = workingDirectory;
115
116                         startInfo.RedirectStandardOutput = true;
117                         startInfo.RedirectStandardError = true;
118                         startInfo.RedirectStandardInput = redirectStandardInput;
119                         startInfo.UseShellExecute = false;
120                         startInfo.CreateNoWindow = true;
121
122                         return startInfo;
123                 }
124
125                 public static void ProcessEnvironmentVariableOverrides (ProcessStartInfo info, StringDictionary environmentOverride)
126                 {
127                         if (globalEnvironmentVariablesOverride != null)
128                                 foreach (DictionaryEntry entry in globalEnvironmentVariablesOverride)
129                                         ProcessEnvironmentVariable (info, (string)entry.Key, (string)entry.Value);
130
131                         if (environmentOverride != null)
132                                 foreach (DictionaryEntry entry in environmentOverride)
133                                         ProcessEnvironmentVariable (info, (string)entry.Key, (string)entry.Value);
134                 }
135
136                 static void ProcessEnvironmentVariable (ProcessStartInfo info, string name, string value)
137                 {
138                         if (value == null && info.EnvironmentVariables.ContainsKey (name))
139                                 info.EnvironmentVariables.Remove (name);
140                         else
141                                 info.EnvironmentVariables[name] = value;
142                 }
143
144         }
145
146         class OutWriter
147         {
148                 TextWriter writer;
149
150                 public OutWriter (TextWriter writer)
151                 {
152                         this.writer = writer;
153                 }
154
155                 public void WriteOut (object sender, string s)
156                 {
157                         writer.Write (s);
158                 }
159
160                 public static ProcessEventHandler GetWriteHandler (TextWriter tw)
161                 {
162                         return tw != null ? new ProcessEventHandler(new OutWriter (tw).WriteOut) : null;
163                 }
164         }
165 }
166
167 #endif