in ClrMemDiag/Utilities/command.cs [394:519]
public Command(string commandLine, CommandOptions options)
{
_options = options;
_commandLine = commandLine;
// See if the command is quoted and match it in that case
Match m = Regex.Match(commandLine, "^\\s*\"(.*?)\"\\s*(.*)");
if (!m.Success)
m = Regex.Match(commandLine, @"\s*(\S*)\s*(.*)"); // thing before first space is command
ProcessStartInfo startInfo = new ProcessStartInfo(m.Groups[1].Value, m.Groups[2].Value);
_process = new Process();
_process.StartInfo = startInfo;
_output = new StringBuilder();
if (options.elevate)
{
options.useShellExecute = true;
startInfo.Verb = "runas";
if (options.currentDirectory == null)
options.currentDirectory = Environment.CurrentDirectory;
}
startInfo.CreateNoWindow = options.noWindow;
if (options.useShellExecute)
{
startInfo.UseShellExecute = true;
if (options.noWindow)
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
}
else
{
if (options.input != null)
startInfo.RedirectStandardInput = true;
startInfo.UseShellExecute = false;
startInfo.RedirectStandardError = true;
startInfo.RedirectStandardOutput = true;
startInfo.ErrorDialog = false;
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.CreateNoWindow = true;
_process.OutputDataReceived += new DataReceivedEventHandler(OnProcessOutput);
_process.ErrorDataReceived += new DataReceivedEventHandler(OnProcessOutput);
}
if (options.environmentVariables != null)
{
// copy over the environment variables to the process startInfo options.
foreach (string key in options.environmentVariables.Keys)
{
// look for %VAR% strings in the value and subtitute the appropriate environment variable.
string value = options.environmentVariables[key];
if (value != null)
{
int startAt = 0;
for (; ;)
{
m = new Regex(@"%(\w+)%").Match(value, startAt);
if (!m.Success) break;
string varName = m.Groups[1].Value;
string varValue;
if (startInfo.EnvironmentVariables.ContainsKey(varName))
varValue = startInfo.EnvironmentVariables[varName];
else
{
varValue = Environment.GetEnvironmentVariable(varName);
if (varValue == null)
varValue = "";
}
// replace this instance of the variable with its definition.
int varStart = m.Groups[1].Index - 1; // -1 becasue % chars are not in the group
int varEnd = varStart + m.Groups[1].Length + 2; // +2 because % chars are not in the group
value = value.Substring(0, varStart) + varValue + value.Substring(varEnd, value.Length - varEnd);
startAt = varStart + varValue.Length;
}
}
startInfo.EnvironmentVariables[key] = value;
}
}
startInfo.WorkingDirectory = options.currentDirectory;
_outputStream = options.outputStream;
if (options.outputFile != null)
{
_outputStream = File.CreateText(options.outputFile);
}
#if false
if (options.showCommand && outputStream != null)
{
// TODO why only for output streams?
outputStream.WriteLine("RUN CMD: " + commandLine);
}
#endif
#if false
// Make sure we kill this task when Ctrl C or appdomain unloads
if (!options.noWait)
AddCommandToCleanupList(this);
#endif
try
{
_process.Start();
}
catch (Exception e)
{
string msg = "Failure starting Process\r\n" +
" Exception: " + e.Message + "\r\n" +
" Cmd: " + commandLine + "\r\n";
if (Regex.IsMatch(startInfo.FileName, @"^(copy|dir|del|color|set|cd|cdir|md|mkdir|prompt|pushd|popd|start|assoc|ftype)", RegexOptions.IgnoreCase))
msg += " Cmd " + startInfo.FileName + " implemented by Cmd.exe, fix by prefixing with 'cmd /c'.";
throw new ApplicationException(msg, e);
}
if (!startInfo.UseShellExecute)
{
// startInfo asyncronously collecting output
_process.BeginOutputReadLine();
_process.BeginErrorReadLine();
}
// Send any input to the command
if (options.input != null)
{
_process.StandardInput.Write(options.input);
_process.StandardInput.Close();
}
}