A result of executing the GUI macro.
Example #1
0
        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);
            }
        }
Example #3
0
        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));
        }