public Task <GuiMacroResult> ExecuteViaExtenderProcessAsync([NotNull] string macrotext, int nConEmuPid, [NotNull] string sConEmuConsoleExtenderExecutablePath) { if (macrotext == null) { throw new ArgumentNullException(nameof(macrotext)); } if (sConEmuConsoleExtenderExecutablePath == null) { throw new ArgumentNullException(nameof(sConEmuConsoleExtenderExecutablePath)); } // conemuc.exe -silent -guimacro:1234 print("\e","git"," --version","\n") var cmdl = new CommandLineBuilder(); cmdl.AppendSwitch("-silent"); cmdl.AppendSwitchIfNotNull("-GuiMacro:", nConEmuPid.ToString()); cmdl.AppendSwitch(macrotext /* appends the text unquoted for cmdline */); if (sConEmuConsoleExtenderExecutablePath == "") { throw new InvalidOperationException("The ConEmu Console Extender Executable is not available."); } if (!File.Exists(sConEmuConsoleExtenderExecutablePath)) { throw new InvalidOperationException($"The ConEmu Console Extender Executable does not exist on disk at “{sConEmuConsoleExtenderExecutablePath}”."); } try { Task <GuiMacroResult> taskStart = Task.Run(() => { var processExtender = new Process() { StartInfo = new ProcessStartInfo(sConEmuConsoleExtenderExecutablePath, cmdl.ToString()) { WindowStyle = ProcessWindowStyle.Hidden, CreateNoWindow = true, RedirectStandardError = true, RedirectStandardOutput = true, UseShellExecute = false } }; processExtender.EnableRaisingEvents = true; var sbResult = new StringBuilder(); DataReceivedEventHandler FOnData = (sender, args) => { lock (sbResult) sbResult.Append(args.Data); }; processExtender.OutputDataReceived += FOnData; processExtender.ErrorDataReceived += FOnData; var taskresult = new TaskCompletionSource <GuiMacroResult>(); processExtender.Exited += delegate { GuiMacroResult result; lock (sbResult) result = new GuiMacroResult() { IsSuccessful = processExtender.ExitCode == 0, Response = sbResult.ToString() }; taskresult.SetResult(result); }; processExtender.Start(); processExtender.BeginOutputReadLine(); processExtender.BeginErrorReadLine(); return(taskresult.Task); }); return(taskStart); } catch (Exception ex) { throw new InvalidOperationException($"Could not run the ConEmu Console Extender Executable at “{sConEmuConsoleExtenderExecutablePath}” with command-line arguments “{cmdl}”.", ex); } }
public Task<GuiMacroResult> ExecuteViaExtenderProcessAsync([NotNull] string macrotext, int nConEmuPid, [NotNull] string sConEmuConsoleExtenderExecutablePath) { if(macrotext == null) throw new ArgumentNullException(nameof(macrotext)); if(sConEmuConsoleExtenderExecutablePath == null) throw new ArgumentNullException(nameof(sConEmuConsoleExtenderExecutablePath)); // conemuc.exe -silent -guimacro:1234 print("\e","git"," --version","\n") var cmdl = new CommandLineBuilder(); cmdl.AppendSwitch("-silent"); cmdl.AppendSwitchIfNotNull("-GuiMacro:", nConEmuPid.ToString()); cmdl.AppendSwitch(macrotext /* appends the text unquoted for cmdline */); if(sConEmuConsoleExtenderExecutablePath == "") throw new InvalidOperationException("The ConEmu Console Extender Executable is not available."); if(!File.Exists(sConEmuConsoleExtenderExecutablePath)) throw new InvalidOperationException($"The ConEmu Console Extender Executable does not exist on disk at “{sConEmuConsoleExtenderExecutablePath}”."); try { Task<Task<GuiMacroResult>> taskStart = Task.Factory.StartNew(() => { var processExtender = new Process() {StartInfo = new ProcessStartInfo(sConEmuConsoleExtenderExecutablePath, cmdl.ToString()) {WindowStyle = ProcessWindowStyle.Hidden, CreateNoWindow = true, RedirectStandardError = true, RedirectStandardOutput = true, UseShellExecute = false}}; processExtender.EnableRaisingEvents = true; var sbResult = new StringBuilder(); DataReceivedEventHandler FOnData = (sender, args) => { lock(sbResult) sbResult.Append(args.Data); }; processExtender.OutputDataReceived += FOnData; processExtender.ErrorDataReceived += FOnData; var taskresult = new TaskCompletionSource<GuiMacroResult>(); processExtender.Exited += delegate { GuiMacroResult result; lock(sbResult) result = new GuiMacroResult() {IsSuccessful = processExtender.ExitCode == 0, Response = sbResult.ToString()}; taskresult.SetResult(result); }; processExtender.Start(); processExtender.BeginOutputReadLine(); processExtender.BeginErrorReadLine(); return taskresult.Task; }); return taskStart.Unwrap(); } catch(Exception ex) { throw new InvalidOperationException($"Could not run the ConEmu Console Extender Executable at “{sConEmuConsoleExtenderExecutablePath}” with command-line arguments “{cmdl}”.", ex); } }
public static async Task <GetInfoRoot> QueryAsync([NotNull] ConEmuSession session) { if (session == null) { throw new ArgumentNullException(nameof(session)); } GuiMacroResult result = await session.BeginGuiMacro("GetInfo").WithParam("Root").ExecuteAsync(); Trace.WriteLine("[ROOT]: " + result.Response); if (!result.IsSuccessful) { throw new InvalidOperationException("The GetInfo-Root call did not succeed."); } if (string.IsNullOrWhiteSpace(result.Response)) // Might yield an empty string randomly if not ready yet { throw new InvalidOperationException("The GetInfo-Root call has yielded an empty result."); } // Interpret the string as XML var xmlDoc = new XmlDocument(); try { xmlDoc.LoadXml(result.Response); } catch (Exception ex) { // Could not parse the XML response. Not expected. Wait more. throw new InvalidOperationException($"The GetInfo-Root call result “{result.Response}” were not a valid XML document.", ex); } XmlElement xmlRoot = xmlDoc.DocumentElement; if (xmlRoot == null) { throw new InvalidOperationException($"The GetInfo-Root call result “{result.Response}” didn't have a root XML element."); } // Current possible records: // <Root State="NotStarted" Name="cmd.exe" /> // <Root State="Running" Name="cmd.exe" PID="4672" ExitCode="259" UpTime="4406" /> // <Root State="Exited" Name="cmd.exe" PID="4672" ExitCode="0" UpTime="14364"/> // Also, there's the State="Empty" documented, though it would be hard to catch // Start with detecting the state string sState = xmlRoot.GetAttribute("State"); if (string.IsNullOrWhiteSpace(sState)) { throw new InvalidOperationException($"The GetInfo-Root call result “{result.Response}” didn't specify the current ConEmu state."); } States state; if (!Enum.TryParse(sState, false, out state)) { throw new InvalidOperationException($"The GetInfo-Root call result “{result.Response}” specifies the State “{sState}” which cannot be matched against the list of the known states {Enum.GetValues(typeof(States)).OfType<States>().Select(o => o.ToString()).OrderBy(o => o, StringComparer.InvariantCultureIgnoreCase).Aggregate((x, y) => x + ", " + y)}."); } string sName = xmlRoot.GetAttribute("Name"); uint nPidRaw; uint?nPid = ((state == States.Running) && (uint.TryParse(xmlRoot.GetAttribute("PID"), NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out nPidRaw))) ? nPidRaw : default(uint?); int nExitCodeRaw; int?nExitCode = ((state == States.Exited) && (int.TryParse(xmlRoot.GetAttribute("ExitCode"), NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out nExitCodeRaw))) ? nExitCodeRaw : default(int?); return(new GetInfoRoot(state, sName, nPid, nExitCode)); }