/// <summary>
        /// initialize contextual attributes and setup the context streams
        /// </summary>
        /// <param name="commandEvaluationContext">context</param>
        public void Initialize(CommandEvaluationContext commandEvaluationContext)
        {
            this.CommandEvaluationContext = commandEvaluationContext;

            // TODO: activate after DotNetConsole is no more static - see remarks below

            /*
             * Out = new ConsoleTextWriterWrapper(System.Console.Out);
             * Err = new TextWriterWrapper(System.Console.Error);
             * In = System.Console.In;
             */

            var scriptOptions = ScriptOptions.Default;
            var abl           = Assembly.GetExecutingAssembly();

            scriptOptions = scriptOptions.WithReferences(abl);
            var cSharpScriptEngine = new CSharpScriptEngine(scriptOptions);

            //Out = DotNetConsole.Out;
            Out = new ShellConsoleTextWriterWrapper(
                commandEvaluationContext,
                System.Console.Out,
                cSharpScriptEngine
                );

            /*
             *  it can exists only one wrapper for out,
             *  between the command evaluation context and dot net console
             */
            DotNetConsole.Out = Out;

            Err = DotNetConsole.Err;
            In  = DotNetConsole.In;

            commandEvaluationContext.SetStreams(Out, In, Err);
        }
Пример #2
0
 public int ShellExec(
     CommandEvaluationContext context,
     string comPath,
     string args,
     string workingDirectory         = null,
     bool waitForExit                = true,
     bool isStreamsEchoEnabled       = true,
     bool isOutputCaptureEnabled     = true,
     bool mergeErrorStreamIntoOutput = true
     )
 {
     return(ShellExec(
                context,
                comPath,
                args,
                workingDirectory,
                out _,
                waitForExit,
                isStreamsEchoEnabled,
                isOutputCaptureEnabled,
                mergeErrorStreamIntoOutput,
                false
                ));
 }
Пример #3
0
        ExpressionEvaluationResult AnalysisPipelineParseResult(
            CommandEvaluationContext context,
            PipelineParseResult pipelineParseResult,
            string expr,
            int outputX,
            ParseResult parseResult
            )
        {
            ExpressionEvaluationResult r = null;
            var errorText = "";

            string[] t;
            int      idx;
            string   serr;

            switch (parseResult.ParseResultType)
            {
            case ParseResultType.Empty:

                r = new ExpressionEvaluationResult(expr, null, parseResult.ParseResultType, null, (int)ReturnCode.OK, null);
                break;

            case ParseResultType.NotValid:      /* command syntax not valid */

                var perComErrs = new Dictionary <string, List <CommandSyntaxParsingResult> >();
                foreach (var prs in parseResult.SyntaxParsingResults)
                {
                    if (prs.CommandSyntax != null)
                    {
                        if (perComErrs.TryGetValue(prs.CommandSyntax?.CommandSpecification?.Name, out var lst))
                        {
                            lst.Add(prs);
                        }
                        else
                        {
                            perComErrs.Add(prs.CommandSyntax.CommandSpecification.Name, new List <CommandSyntaxParsingResult> {
                                prs
                            });
                        }
                    }
                }

                var errs           = new List <string>();
                var minErrPosition = int.MaxValue;
                var errPositions   = new List <int>();
                foreach (var kvp in perComErrs)
                {
                    var comSyntax = kvp.Value.First().CommandSyntax;
                    foreach (var prs in kvp.Value)
                    {
                        foreach (var perr in prs.ParseErrors)
                        {
                            minErrPosition = Math.Min(minErrPosition, perr.Position);
                            errPositions.Add(perr.Position);
                            if (!errs.Contains(perr.Description))
                            {
                                errs.Add(perr.Description);
                            }
                        }
                        errorText += Br + Red + string.Join(Br + Red, errs);
                    }
                    errorText += $"{Br}{Red}for syntax: {comSyntax}{Br}";
                }

                errPositions.Sort();
                errPositions = errPositions.Distinct().ToList();

                t = new string[expr.Length + 2];
                for (int i = 0; i < t.Length; i++)
                {
                    t[i] = " ";
                }
                foreach (var errPos in errPositions)
                {
                    t[GetIndex(context, errPos, expr)] = Settings.ErrorPositionMarker + "";
                }
                serr = string.Join("", t);
                Error(" ".PadLeft(outputX + 1) + serr, false, false);

                Error(errorText);
                r = new ExpressionEvaluationResult(expr, errorText, parseResult.ParseResultType, null, (int)ReturnCode.NotIdentified, null);
                break;

            case ParseResultType.Ambiguous:

                errorText += $"{Red}ambiguous syntaxes:{Br}";
                foreach (var prs in parseResult.SyntaxParsingResults)
                {
                    errorText += $"{Red}{prs.CommandSyntax}{Br}";
                }
                Error(errorText);
                r = new ExpressionEvaluationResult(expr, errorText, parseResult.ParseResultType, null, (int)ReturnCode.NotIdentified, null);
                break;

            case ParseResultType.NotIdentified:

                t = new string[expr.Length + 2];
                for (int j = 0; j < t.Length; j++)
                {
                    t[j] = " ";
                }
                var err = parseResult.SyntaxParsingResults.First().ParseErrors.First();
                idx        = err.Position;
                t[idx]     = Settings.ErrorPositionMarker + "";
                errorText += Red + err.Description;
                serr       = string.Join("", t);
                context.Errorln(" ".PadLeft(outputX) + serr);
                context.Errorln(errorText);
                r = new ExpressionEvaluationResult(expr, errorText, parseResult.ParseResultType, null, (int)ReturnCode.NotIdentified, null);
                break;

            case ParseResultType.SyntaxError:

                t = new string[expr.Length + 2];
                for (int j = 0; j < t.Length; j++)
                {
                    t[j] = " ";
                }
                var err2 = parseResult.SyntaxParsingResults.First().ParseErrors.First();
                idx        = err2.Index;
                t[idx]     = Settings.ErrorPositionMarker + "";
                errorText += Red + err2.Description;
                serr       = string.Join("", t);
                context.Errorln(" ".PadLeft(outputX) + serr);
                context.Errorln(errorText);
                r = new ExpressionEvaluationResult(expr, errorText, parseResult.ParseResultType, null, (int)ReturnCode.NotIdentified, null);
                break;
            }

            return(r);
        }
Пример #4
0
        /// <summary>
        /// exec a file with os shell exec or orbsh shell exec
        /// </summary>
        /// <param name="context">command evaluation context</param>
        /// <param name="comPath">command filePath</param>
        /// <param name="args">command line arguments string</param>
        /// <param name="output">shell exec result if any</param>
        /// <param name="waitForExit">true if wait for exec process exits</param>
        /// <param name="isStreamsEchoEnabled">if true, exec process output stream is echoized to context out (dump command output)</param>
        /// <param name="isOutputCaptureEnabled">if true capture the exec process output and give the result in parameter 'output'</param>
        /// <param name="mergeErrorStreamIntoOutput">if true merge exec process err stream content to the process output content (if process out capture is enabled)</param>
        /// <returns>exec process return code</returns>
        public int ShellExec(
            CommandEvaluationContext context,
            string comPath,
            string args,
            string workingDirectory,
            out string output,
            bool waitForExit                = true,
            bool isStreamsEchoEnabled       = true,
            bool isOutputCaptureEnabled     = true,
            bool mergeErrorStreamIntoOutput = true,
            bool redirectStandardInput      = false
            )
        {
            Thread         inputTask = null;
            TextReader     stdin     = null;
            ProcessWrapper pw        = null;

            try
            {
                output = null;
                workingDirectory ??= Environment.CurrentDirectory;
                var processStartInfo = new ProcessStartInfo()
                {
                    UseShellExecute = false,
                    //StandardOutputEncoding = Encoding.UTF8,   // keep system default
                    //StandardErrorEncoding = Encoding.UTF8,    // keep system default

                    RedirectStandardError  = true,
                    RedirectStandardInput  = redirectStandardInput, // allows access to process StandardInput
                    RedirectStandardOutput = true,
                    CreateNoWindow         = true,
                    FileName         = comPath,
                    Arguments        = args,
                    WindowStyle      = ProcessWindowStyle.Normal,
                    WorkingDirectory = workingDirectory
                };
                var sb = new StringBuilder();

                // batch shell exec ?

                if (Path.GetExtension(comPath) == context.ShellEnv.GetValue <string>(ShellEnvironmentVar.settings_clp_shellExecBatchExt))
                {
                    var batchMethod = typeof(CommandLineProcessorCommands).GetMethod(nameof(CommandLineProcessorCommands.Batch));
                    var r           = Eval(context, batchMethod, "\"" + FileSystemPath.UnescapePathSeparators(comPath) + " " + args + "\"", 0);
                    output = sb.ToString();
                    return(r.EvalResultCode);
                }

                // process exec

                pw = ProcessWrapper.ThreadRun(
                    processStartInfo,
                    null,
                    (outStr) =>
                {
                    if (isStreamsEchoEnabled)
                    {
                        context.Out.Echoln(outStr);
                    }
                    if (isOutputCaptureEnabled)
                    {
                        sb.AppendLine(outStr);
                    }
                },
                    (errStr) =>
                {
                    if (isStreamsEchoEnabled)
                    {
                        context.Errorln(errStr);
                    }
                    if (isOutputCaptureEnabled && mergeErrorStreamIntoOutput)
                    {
                        sb.AppendLine(errStr);
                    }
                }
                    );

                if (context.ShellEnv.IsOptionSetted(ShellEnvironmentVar.settings_clp_enableShellExecTraceProcessStart))
                {
                    context.Out.Echoln($"{context.ShellEnv.Colors.TaskInformation}process '{Path.GetFileName(comPath)}' [{pw.Process.Id}] started(rdc)");
                }

                int retCode = 0;
                int c       = -1;

                if (waitForExit)
                {
                    if (redirectStandardInput)
                    {
                        inputTask = new Thread(
                            () =>
                        {
                            try
                            {
                                var cp = comPath;
                                stdin  = System.Console.In;

#if dbg
                                Debug.WriteLine($"input task started [ cp = {cp} ]");
#endif

                                while (!(bool)pw?.Process?.HasExited)
                                {
                                    if (System.Console.KeyAvailable)
                                    {
                                        var key = System.Console.ReadKey(true);
                                        c       = key.KeyChar;

                                        if (c > -1)
                                        {
                                            context.Out.ConsolePrint("" + (char)c);

#if dbg
                                            Debug.Write((char)c);
#endif

                                            pw?.Process.StandardInput.Write((char)c);
                                            pw?.Process.StandardInput.Flush();
                                        }
                                    }

                                    Thread.Sleep(1);
                                }

#if dbg
                                Debug.WriteLine("input task exited");
#endif
                            }
                            catch
#if dbg
                            (Exception ex)
#endif
                            {
#if dbg
                                Debug.WriteLine($"input task exited ({ex.Message})");
#endif
                            }
                        });
                        inputTask.Name = "forward input task";
                        inputTask.Start();
                    }

                    var cancellationTask = Task.Run(() =>
                    {
                        try
                        {
                            while (!(bool)pw?.Process?.HasExited)
                            {
                                if (IsCancellationRequested)
                                {
                                    pw?.Process?.Kill();
                                }
                                Thread.Sleep(1);
                            }

                            inputTask?.Interrupt();

#if dbg
                            Debug.WriteLine($"cancellation task exited");
#endif
                        }
                        catch
#if dbg
                        (Exception ex)
#endif
                        {
#if dbg
                            Debug.WriteLine($"cancellation task exited ({ex.Message})");
#endif
                        }
                    });

                    pw.Process.WaitForExit();

                    retCode = pw.Process.ExitCode;

                    pw.StdOutCallBackThread.Join();
                    pw.StdErrCallBackThread.Join();

                    output = sb.ToString();
                }

                if (context.ShellEnv.IsOptionSetted(ShellEnvironmentVar.settings_clp_enableShellExecTraceProcessEnd))
                {
                    context.Out.Echoln($"{context.ShellEnv.Colors.TaskInformation}process '{Path.GetFileName(comPath)}' exited with code: {retCode}(rdc)");
                }

                return(retCode);
            }
            catch (Exception shellExecException)
            {
                inputTask?.Interrupt();
                throw new Exception($"ShellExec error: {shellExecException}", shellExecException);
            }
            finally
            {
            }
        }