/// <summary> /// Launch a new command and returns the Command object that can be used to monitor /// the restult. It does not wait for the command to complete, however you /// can call 'Wait' to do that, or use the 'Run' or 'RunToConsole' methods. */ /// </summary> /// <param variable="commandLine">The command lineNumber to run as a subprocess</param> /// <param variable="options">Additional qualifiers that control how the process is run</param> /// <returns>A Command structure that can be queried to determine ExitCode, Output, etc.</returns> public Command(string commandLine, CommandOptions options) { this.options = options; this.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) { #if NETSTANDARD1_6 throw new NotImplementedException("Launching elevated processes is not implemented when TraceEvent is built for NetStandard 1.6"); #else options.useShellExecute = true; startInfo.Verb = "runas"; if (options.currentDirectory == null) { options.currentDirectory = Directory.GetCurrentDirectory(); } #endif } startInfo.CreateNoWindow = options.noWindow; if (options.useShellExecute) { startInfo.UseShellExecute = true; #if !NETSTANDARD1_6 if (options.noWindow) { startInfo.WindowStyle = ProcessWindowStyle.Hidden; } #endif } else { if (options.input != null) { startInfo.RedirectStandardInput = true; } startInfo.UseShellExecute = false; startInfo.RedirectStandardError = true; startInfo.RedirectStandardOutput = true; #if !NETSTANDARD1_6 startInfo.ErrorDialog = false; startInfo.WindowStyle = ProcessWindowStyle.Hidden; #endif 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.GetEnvironment().ContainsKey(varName)) { varValue = startInfo.GetEnvironment()[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 because % 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.GetEnvironment()[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 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.Dispose(); } }
/// <summary> /// Launch a new command and returns the Command object that can be used to monitor /// the restult. It does not wait for the command to complete, however you /// can call 'Wait' to do that, or use the 'Run' or 'RunToConsole' methods. */ /// </summary> /// <param variable="commandLine">The command lineNumber to run as a subprocess</param> /// <param variable="options">Additional qualifiers that control how the process is run</param> /// <returns>A Command structure that can be queried to determine ExitCode, Output, etc.</returns> public Command(string commandLine, CommandOptions options) { this.options = options; this.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); } 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(); } }
/// <summary> /// Run 'commandLine', sending the output to the console, and wait for the command to complete. /// This simulates what batch filedo when executing their commands. It is a bit more verbose /// by default, however /// </summary> /// <param variable="commandLine">The command lineNumber to run as a subprocess</param> /// <param variable="options">Additional qualifiers that control how the process is run</param> /// <returns>A Command structure that can be queried to determine ExitCode, Output, etc.</returns> public static Command RunToConsole(string commandLine, CommandOptions options) { return Run(commandLine, options.Clone().AddOutputStream(Console.Out)); }
/// <summary> /// Run 'commandLine' as a subprocess and waits for the command to complete. /// Output is captured and placed in the 'Output' property of the returned Command /// structure. /// </summary> /// <param variable="commandLine">The command lineNumber to run as a subprocess</param> /// <param variable="options">Additional qualifiers that control how the process is run</param> /// <returns>A Command structure that can be queried to determine ExitCode, Output, etc.</returns> public static Command Run(string commandLine, CommandOptions options) { Command run = new Command(commandLine, options); run.Wait(); return run; }
/// <summary> /// Run 'commandLine', sending the output to the console, and wait for the command to complete. /// This simulates what batch filedo when executing their commands. It is a bit more verbose /// by default, however /// </summary> /// <param variable="commandLine">The command lineNumber to run as a subprocess</param> /// <param variable="options">Additional qualifiers that control how the process is run</param> /// <returns>A Command structure that can be queried to determine ExitCode, Output, etc.</returns> public static Command RunToConsole(string commandLine, CommandOptions options) { return(Run(commandLine, options.Clone().AddOutputStream(Console.Out))); }