Пример #1
0
 /// <summary>
 /// Handles the tab key by calling all registered tab completion handlers.
 /// </summary>
 /// <param name="context">Context that can be used to inspect the current command line to perform tab completion</param>
 public void Handle(RichCommandLineContext context)
 {
     context.Intercept = true;
     context.RefreshTokenInfo();
     try
     {
         foreach (var handler in TabCompletionHandlers)
         {
             if (handler.TryTabComplete(context))
             {
                 break;
             }
         }
     }
     catch (Exception ex)
     {
         if (ThrowOnTabCompletionHandlerException)
         {
             throw;
         }
         else
         {
             PowerLogger.LogLine("Tab completion handler threw exception: " + ex.ToString());
         }
     }
 }
        internal void Drain(bool block = true)
        {
            if (_stages.Count > 0)
            {
                _stages.First().Drain();
            }

            while (block && IsDrained == false)
            {
                Thread.Sleep(10);
            }
            if (block)
            {
                PowerLogger.LogLine("The pipeline is drained");
                lock (asyncExceptionLock)
                {
                    try
                    {
                        if (asyncExceptions.Count == 1)
                        {
                            throw asyncExceptions.First();
                        }
                        else if (asyncExceptions.Count > 1)
                        {
                            throw new AggregateException(asyncExceptions.ToArray());
                        }
                    }
                    finally
                    {
                        asyncExceptions.Clear();
                    }
                }
            }
        }
        private void DoSyntaxHighlighting(RichCommandLineContext context)
        {
            if (Highlighter == null)
            {
                return;
            }

            bool highlightChanged = false;

            try
            {
                highlightChanged = Highlighter.TryHighlight(context);
            }
            catch (Exception ex)
            {
                if (ThrowOnSyntaxHighlightException)
                {
                    throw;
                }
                else
                {
                    PowerLogger.LogLine("Syntax highlighting threw exception: " + ex.ToString());
                }
            }

            if (highlightChanged)
            {
                context.RefreshConsole(0, 0);
            }
        }
Пример #4
0
        public void Double([ArgPipelineTarget(PipelineOnly = false)] double number)
        {
            var output = 2 * number;

            PowerLogger.LogLine("Double of " + number + " is " + output);
            Console.Write(number + " - I am the doubler, ");
            ConsoleString.WriteLine("Muahahahaha!", ConsoleColor.Green);
            ArgPipeline.Push(output);
        }
        private static bool TryLoadAddInObject <TAttr, TBaseReq>(out TBaseReq result, params object[] constructorParams)
        {
            Type targetType = null;

            var powerArgsDir = Path.GetDirectoryName(typeof(Args).Assembly.Location);

            foreach (Assembly toInspect in GetSearchAssemblyCache())
            {
                try
                {
                    var match = (from t in toInspect.GetTypes() where t.HasAttr <TAttr>() && (t.GetInterfaces().Contains(typeof(TBaseReq)) || t.IsSubclassOf(typeof(TBaseReq))) select t).FirstOrDefault();
                    if (match != null)
                    {
                        targetType = match;
                        break;
                    }
                }
                catch (Exception ex)
                {
                    PowerLogger.LogLine("Exception trying to reflect over an assembly to get type info: " + ex.ToString());
                }
            }

            if (targetType == null)
            {
                PowerLogger.LogLine("Could not find an object with a base of " + typeof(TBaseReq).FullName + " that had attribute " + typeof(TAttr).FullName);
                result = default(TBaseReq);
                return(false);
            }

            try
            {
                result = (TBaseReq)Activator.CreateInstance(targetType, constructorParams);
                return(true);
            }
            catch (TargetInvocationException ex)
            {
                if (ex.InnerException == null)
                {
                    throw;
                }
                if (ex.InnerException is ArgException)
                {
                    throw ex.InnerException;
                }

                result = default(TBaseReq);
                return(false);
            }
            catch (Exception ex)
            {
                PowerLogger.LogLine("Could not initialize target type " + targetType.FullName + "\n\n" + ex.ToString());
                result = default(TBaseReq);
                return(false);
            }
        }
Пример #6
0
        /// <summary>
        /// This is the main hook point where the pipeline features get injected.  This method is responsible for creating the pipeline if needed.  It is also
        /// responsible for connecting to an external program if this program was launched by another program's pipeline manager.  It is also responsible for
        /// supporting any pipeline stage actions (e.g. $filter) that are not supported if the [ArgPipeline] metadata is omitted from the root definition.
        /// </summary>
        /// <param name="context">The processing context</param>
        public override void BeforeParse(ArgHook.HookContext context)
        {
            ExternalPipelineInputStage externalStage;

            if (ExternalPipelineProvider.TryLoadInputStage(context.Definition, context.CmdLineArgs, out externalStage) && externalStage.IsProgramLaunchedByExternalPipeline)
            {
                externalStage.CommandLineDefinitionFactory = this.commandLineDeinitionFactory;
                while (externalStage.IsDrained == false)
                {
                    Thread.Sleep(10);
                }
                PowerLogger.LogLine("Input stage drained");
                context.CancelAllProcessing();
                return;
            }
            else if (context.CmdLineArgs.Contains(PowerArgsPipeIndicator))
            {
                ValidatePipeline(context);
                List <List <string> > stageCommandLines = new List <List <string> >();
                stageCommandLines.Add(new List <string>());

                for (int i = 0; i < context.CmdLineArgs.Length; i++)
                {
                    var arg = context.CmdLineArgs[i];
                    if (arg == PowerArgsPipeIndicator)
                    {
                        stageCommandLines.Add(new List <string>());
                    }
                    else
                    {
                        stageCommandLines.Last().Add(arg);
                    }
                }

                context.CmdLineArgs = stageCommandLines.First().ToArray();

                var manager = GetPipelineManagerFromContext(context);

                for (int i = 0; i < stageCommandLines.Count; i++)
                {
                    var args = stageCommandLines[i];
                    if (args.Count == 0)
                    {
                        throw new ArgException("Missing action after pipeline indicator: " + PowerArgsPipeIndicator);
                    }
                    manager.CreateNextStage(context, args.ToArray(), this.commandLineDeinitionFactory);
                }

                context.CmdLineArgs = manager.Stages[0].CmdLineArgs.ToArray();
            }
            else
            {
                // do nothing
            }
        }
Пример #7
0
        public void Main()
        {
            object eval;

            if (PropertyName == "$item")
            {
                eval = FilterTarget;
            }
            else
            {
                var evalProp = FilterTarget.GetType().GetProperty(PropertyName);
                if (evalProp == null)
                {
                    return;
                }
                if (evalProp.GetGetMethod() == null)
                {
                    return;
                }

                eval = evalProp.GetValue(FilterTarget, null);
                if (eval == null)
                {
                    return;
                }
            }

            if (eval is string == false && (Operator == FilterOperators.Contains || Operator == FilterOperators.NotContains))
            {
                throw new ArgException("The Contains and NotContains operators can only be applied to properties of type string");
            }

            object comparison = Value;

            try
            {
                if (eval.GetType() != typeof(string))
                {
                    if (ArgRevivers.CanRevive(eval.GetType()))
                    {
                        comparison = ArgRevivers.Revive(eval.GetType(), "", comparison + "");
                    }
                }
            }
            catch (Exception ex)
            {
                PowerLogger.LogLine("Unable to convert a string to:" + eval.GetType().FullName);
                return;
            }

            if (FilterLogic.FilterAcceptsObject(eval, Operator, comparison))
            {
                ArgPipeline.Push(FilterTarget);
            }
        }
Пример #8
0
        private void Dispatch(HttpListenerContext context)
        {
            try
            {
                var request = context.Request;
                using (var reader = new StreamReader(request.InputStream))
                {
                    var body    = reader.ReadToEnd();
                    var message = JsonConvert.DeserializeObject <HttpPipelineMessage>(body);

                    HttpPipelineControlResponse responseMessage = new HttpPipelineControlResponse();

                    if (MessageReceivedHandler != null)
                    {
                        try
                        {
                            responseMessage = MessageReceivedHandler(message);
                        }
                        catch (Exception ex)
                        {
                            PowerLogger.LogLine("Receive handler threw an exception");
                            responseMessage.ExceptionInfo = ex.ToString();
                            responseMessage.StatusCode    = HttpStatusCode.BadRequest;
                        }
                    }

                    var resposneMessageContents = JsonConvert.SerializeObject(responseMessage, HttpPipelineMessage.CommonSettings);
                    using (var writer = new StreamWriter(context.Response.OutputStream))
                    {
                        writer.Write(resposneMessageContents);
                    }

                    if (responseMessage.Close)
                    {
                        PowerLogger.LogLine("Closing listener because a response message told us to");
                        Stop();
                    }
                }
            }
            catch (Exception ex)
            {
                if (ListenException != null)
                {
                    ListenException(ex);
                }
                else
                {
                    throw;
                }
            }
        }
Пример #9
0
        public void Stop()
        {
            if (listener.IsListening == false)
            {
                return;
            }

            listener.Stop();
            PowerLogger.LogLine("Listener closed");
            if (Stopped != null)
            {
                Stopped();
            }
        }
Пример #10
0
        /// <summary>
        /// The default implementation is to use the given definition factory to new up a definition and invoke an action using the given command line.  You can
        /// override this if you want to process the given pipeline object in a different way.  You will be called on this stage's processing thread and you should let exceptions
        /// flow through since they'll be bubbled up to the caller directly.
        /// </summary>
        /// <param name="o">An object recceived on the pipeline</param>
        protected virtual void OnObjectReceived(object o)
        {
            var definitionToUse = baseDefinition != null?CommandLineDefinitionFactory.MakeDefinition(baseDefinition) : CommandLineDefinitionFactory.MakeDefinition();

            var childCommandLine = MapObject(o, definitionToUse);

            PowerLogger.LogLine("STAGE - " + StageIndex + " - Executing piped command: " + string.Join(" ", childCommandLine));

            if (definitionToUse.Actions.Count > 0)
            {
                Args.InvokeAction(definitionToUse, childCommandLine);
            }
            else
            {
                Args.InvokeMain(definitionToUse, childCommandLine);
            }
        }
Пример #11
0
        public object MapIncompatibleDirectTargets(Type desiredType, object incompatibleObject)
        {
            if (incompatibleObject is JObject == false)
            {
                throw new ArgumentException("Type not supported, must be JObject: " + incompatibleObject.GetType().FullName);
            }

            var revivedValue = Activator.CreateInstance(desiredType);

            int mappedProps = 0;

            foreach (JProperty prop in ((JObject)(incompatibleObject)).Properties())
            {
                if (prop.Type == JTokenType.Object || prop.Type == JTokenType.Array || prop.Type == JTokenType.Bytes || prop.Type == JTokenType.Constructor || prop.Type == JTokenType.Comment)
                {
                    continue;
                }

                var targetProp = desiredType.GetProperty(prop.Name);

                if (targetProp == null || targetProp.GetSetMethod() == null)
                {
                    continue;
                }

                if (prop.Type == JTokenType.Null)
                {
                    targetProp.SetValue(revivedValue, null, null);
                    mappedProps++;
                }
                else if (ArgRevivers.CanRevive(targetProp.PropertyType))
                {
                    PowerLogger.LogLine("Mapped JObject property to " + desiredType.Name + "." + targetProp.Name);
                    var revivedPropValue = ArgRevivers.Revive(targetProp.PropertyType, prop.Name, prop.Value.ToString());
                    targetProp.SetValue(revivedValue, revivedPropValue, null);
                    mappedProps++;
                }
            }

            if (mappedProps == 0)
            {
                throw new ArgException("Could not map the given object to type: " + desiredType);
            }

            return(revivedValue);
        }
        public override void Accept(object o)
        {
            PowerLogger.LogLine("Sending object over the wire: " + o);
            HttpPipelineControlResponse response = null;

            try
            {
                response = Sender.SendObject(o);
            }
            catch (WebException ex)
            {
                if (ex.Status == WebExceptionStatus.ConnectFailure)
                {
                    try
                    {
                        throw new ArgException("Could not connect to external program '" + exe + "', possibly because it was not built with PowerArgs, or it does not have remote pipelining enabled.  TODO - Help URL here.", ex);
                    }
                    catch (Exception toBubble)
                    {
                        this.Manager.BubbleAsyncException(toBubble);
                    }
                }
                else
                {
                    this.Manager.BubbleAsyncException(ex);
                }
            }
            catch (Exception ex)
            {
                this.Manager.BubbleAsyncException(ex);
            }

            if (response == null)
            {
                return;
            }

            if (response.StatusCode != HttpStatusCode.Accepted)
            {
                this.Manager.BubbleAsyncException(new ArgException("The external program '" + exe + "' could not accept the object of type: " + o.GetType().FullName + "\n\n" + response.ExceptionInfo));
            }
        }
Пример #13
0
        static void Main(string[] args)
        {
            PowerLogger.LogFile = @"C:\temp\ExternalLog-" + DateTime.Now.Ticks + ".log";

            foreach (var arg in args)
            {
                if (arg == "PretendToNotBePowerArgsEnabled")
                {
                    PowerLogger.LogLine("Pretended to not be PowerArgs enabled");
                    return;
                }
            }

            try
            {
                Args.InvokeAction <Program>(args);
                PowerLogger.LogLine("InvokeAction returned without error");
            }
            catch (Exception ex)
            {
                PowerLogger.LogLine("Unhandled top level exception in test program\n\n" + ex.ToString());
            }
        }
Пример #14
0
        private void ProcessLoopImpl()
        {
            while (listener.IsListening)
            {
                try
                {
                    var task = GetContextAsync();
                    try
                    {
                        task.Wait();
                    }
                    catch (Exception)
                    {
                        if (listener.IsListening)
                        {
                            throw;
                        }
                        continue;
                    }

                    lastRequestReceivedTime = DateTime.Now;
                    PowerLogger.LogLine("Listener accepted a request");
                    new Task(() => Dispatch(task.Result)).Start();
                }
                catch (Exception ex)
                {
                    if (ListenException != null)
                    {
                        ListenException(ex);
                    }
                    else
                    {
                        throw;
                    }
                }
            }
        }
        public HttpInputPipelineStage(CommandLineArgumentsDefinition baseDefinition, string[] rawCommandLine)
            : base(baseDefinition, CleanCommandLineOfInputPortInfo(rawCommandLine))
        {
            int port;

            if (TryFindPort(rawCommandLine, out port) == false)
            {
                IsProgramLaunchedByExternalPipeline = false;
                return;
            }
            else
            {
                IsProgramLaunchedByExternalPipeline = true;
            }

            Init.InitIfNotAlreadyDone();

            interceptor = ConsoleOutInterceptor.Instance;
            interceptor.Attach();
            PowerLogger.LogLine("Initializing input pipe for command line on port " + port + ": " + string.Join(" ", this.CmdLineArgs));
            wrappedStage = new InProcessPipelineStage(baseDefinition, this.CmdLineArgs.ToArray());
            listener     = new HttpPipelineMessageListener(port, TimeSpan.FromSeconds(10));

            listener.Timeout += () =>
            {
                PowerLogger.LogLine("HttpInputPipelineStage listener timed out.");
                Process.GetCurrentProcess().Kill();
            };

            wrappedStage.UnhandledException += (ex) =>
            {
                QueueException(ex);
            };

            listener.ListenException += (ex) =>
            {
                QueueException(ex);
            };

            listener.MessageReceivedHandler = (message) =>
            {
                if (message.ControlAction == null)
                {
                    LogLine("Pipe input received");
                    var pipedObject = DeserializePipedObject(message);
                    wrappedStage.CommandLineDefinitionFactory = this.CommandLineDefinitionFactory;
                    wrappedStage.Accept(pipedObject);
                    LogLine("Pipe input processed");
                    return(new HttpPipelineControlResponse()
                    {
                        StatusCode = HttpStatusCode.Accepted
                    });
                }
                else if (message.ControlAction == "Drain")
                {
                    Drain();
                    return(new HttpPipelineControlResponse()
                    {
                        StatusCode = HttpStatusCode.Accepted
                    });
                }
                else if (message.ControlAction == "Poll")
                {
                    LogLine("Poll requested");
                    string pipedObjectArrayJson        = null;
                    string exceptionInfo               = null;
                    List <ConsoleCharacter> textOutput = null;
                    lock (outputQueueLock)
                    {
                        List <object> batch = new List <object>();
                        while (outputQueue.Count > 0)
                        {
                            batch.Add(outputQueue.Dequeue());
                        }

                        if (batch.Count > 0)
                        {
                            LogLine("Pipe output sent");
                            pipedObjectArrayJson = JsonConvert.SerializeObject(batch, HttpPipelineMessage.CommonSettings);
                        }

                        while (exceptionQueue.Count > 0)
                        {
                            LogLine("Exception output sent");
                            exceptionInfo  = exceptionInfo ?? "";
                            exceptionInfo += exceptionQueue.Dequeue().ToString() + Environment.NewLine + Environment.NewLine;
                        }

                        var interceptedText = interceptor.ReadAndClear();

                        while (interceptedText.Count > 0)
                        {
                            textOutput = textOutput ?? new List <ConsoleCharacter>();
                            textOutput.Add(interceptedText.Dequeue());
                        }

                        while (textOutputQueue.Count > 0)
                        {
                            textOutput = textOutput ?? new List <ConsoleCharacter>();
                            textOutput.Add(textOutputQueue.Dequeue());
                        }
                    }
                    return(new HttpPipelineControlResponse()
                    {
                        StatusCode = HttpStatusCode.OK, ExceptionInfo = exceptionInfo, ConsoleOutput = textOutput, PipedObjectArrayJson = pipedObjectArrayJson, Value = wrappedStage.IsDrained + ""
                    });
                }
                else if (message.ControlAction == "Close")
                {
                    LogLine("Close requested");
                    ArgPipeline.ObjectExitedPipeline -= outputHandler;
                    return(new HttpPipelineControlResponse()
                    {
                        StatusCode = HttpStatusCode.OK, Close = true
                    });
                }
                else
                {
                    LogLine("Unrecognized action: " + message.ControlAction);
                    return(new HttpPipelineControlResponse()
                    {
                        StatusCode = HttpStatusCode.BadRequest, ConsoleOutput = new ConsoleString("Unrecognized action: " + message.ControlAction).ToList()
                    });
                }
            };

            outputHandler = (obj) =>
            {
                LogLine("Pipe output queued");
                lock (outputQueueLock)
                {
                    outputQueue.Enqueue(obj);
                }
            };

            ArgPipeline.ObjectExitedPipeline += outputHandler;

            listener.Start();
        }
        /// <summary>
        /// Reads a line of text from the console.  Any interactions you've configured before calling this method will be in effect.
        /// </summary>
        /// <param name="initialBuffer">Optionally seed the prompt with an initial value that the end user can modify</param>
        /// <returns>a line of text from the console</returns>
        public ConsoleString ReadLine(ConsoleString initialBuffer = null)
        {
            RichCommandLineContext context;

            lock (SyncLock)
            {
                context                  = new RichCommandLineContext(this.HistoryManager);
                context.Console          = this.Console;
                context.ConsoleStartTop  = this.Console.CursorTop;
                context.ConsoleStartLeft = this.Console.CursorLeft;
            }

            if (initialBuffer != null)
            {
                lock (SyncLock)
                {
                    context.ReplaceConsole(initialBuffer);
                }
            }

            while (true)
            {
                context.Reset();
                context.KeyPressed = this.Console.ReadKey(true);
                lock (SyncLock)
                {
                    context.CharacterToWrite = new ConsoleCharacter(context.KeyPressed.KeyChar);
                    context.BufferPosition   = this.Console.CursorLeft - context.ConsoleStartLeft + (this.Console.CursorTop - context.ConsoleStartTop) * this.Console.BufferWidth;

                    if (context.BufferPosition < 0 || context.BufferPosition > context.Buffer.Count)
                    {
                        var message = string.Format("The cursor is not located within the bounds of the buffer. Cursor: {0},{1}    Start position: {2},{3}    Buffer position: {4}    Buffer length: {5}", this.Console.CursorTop, this.Console.CursorLeft, context.ConsoleStartTop, context.ConsoleStartLeft, context.BufferPosition, context.Buffer.Count);
                        try
                        {
                            throw new IndexOutOfRangeException(message);
                        }
                        catch (Exception ex)
                        {
                            PowerLogger.LogLine(ex.ToString());
                            throw;
                        }
                    }

                    IKeyHandler handler = null;

                    if (KeyHandlers.TryGetValue(context.KeyPressed.Key, out handler) == false && IsWriteable(context.KeyPressed))
                    {
                        context.WriteCharacterForPressedKey();
                        DoSyntaxHighlighting(context);
                    }
                    else if (handler != null)
                    {
                        handler.Handle(context);

                        if (context.Intercept == false && IsWriteable(context.KeyPressed))
                        {
                            context.WriteCharacterForPressedKey();
                        }

                        DoSyntaxHighlighting(context);

                        if (context.IsFinished)
                        {
                            this.Console.WriteLine();
                            break;
                        }
                    }

                    if (AfterReadKey != null)
                    {
                        AfterReadKey(context);
                    }
                }
            }

            return(new ConsoleString(context.Buffer));
        }
Пример #17
0
        private string[] MapObject(object o, CommandLineArgumentsDefinition effectiveDefinition)
        {
            List <string> newCommandLine = new List <string>();

            newCommandLine.AddRange(CmdLineArgs);

            var preParseResult = ArgParser.Parse(effectiveDefinition, newCommandLine.ToArray());

            var predictedAction = effectiveDefinition.FindMatchingAction(this.CmdLineArgs[0]);

            if (predictedAction == null)
            {
                PowerLogger.LogLine("Could not determine action: " + this.CmdLineArgs[0] + " - Here are the supported action:");
                foreach (var action in effectiveDefinition.Actions)
                {
                    PowerLogger.LogLine("  " + action.DefaultAlias);
                }
                throw new ArgException("TODO - Could not determine action: " + this.CmdLineArgs[0]);
            }

            PowerLogger.LogLine("Predicted action is " + predictedAction.DefaultAlias);


            var argsToInspectForDirectMappingTarget = predictedAction.Arguments.Union(effectiveDefinition.Arguments).ToList();
            var directMappingTarget = (from argument in argsToInspectForDirectMappingTarget
                                       where argument.Metadata.HasMeta <ArgPipelineTarget>()
                                       select argument).SingleOrDefault();

            if (directMappingTarget != null)
            {
                var revivedValue = o;
                if (IsCompatible(o, directMappingTarget) == false)
                {
                    PowerLogger.LogLine("Need to map " + o.GetType().FullName + " to " + directMappingTarget.ArgumentType.FullName);

                    if (TrySimpleConvert(o, directMappingTarget.ArgumentType, out revivedValue))
                    {
                        // we're good
                    }
                    else if (ArgPipelineObjectMapper.CurrentMapper == null)
                    {
                        throw new InvalidArgDefinitionException("Unable to attempt tp map type " + o.GetType().FullName + " to " + directMappingTarget.ArgumentType.FullName + " because no mapper is registered at ArgPipelineObjectMapperProvider.CurrentMapper");
                    }
                    else
                    {
                        revivedValue = ArgPipelineObjectMapper.CurrentMapper.MapIncompatibleDirectTargets(directMappingTarget.ArgumentType, o);
                    }
                }

                effectiveDefinition.Metadata.Add(new ArgumentOverrideHook(directMappingTarget, revivedValue));
            }
            else
            {
                PowerLogger.LogLine("Attempting to shred object: " + o.ToString());
                foreach (var argument in predictedAction.Arguments.Union(effectiveDefinition.Arguments))
                {
                    bool manualOverride = false;

                    foreach (var explicitKey in preParseResult.ExplicitParameters.Keys)
                    {
                        if (argument.IsMatch(explicitKey))
                        {
                            manualOverride = true;
                            break;
                        }
                    }

                    if (preParseResult.ImplicitParameters.ContainsKey(argument.Position))
                    {
                        manualOverride = true;
                    }

                    if (manualOverride)
                    {
                        continue;
                    }

                    var    mapper = argument.Metadata.Meta <ArgPipelineExtractor>() ?? new ArgPipelineExtractor();
                    string mappedKey, mappedValue;
                    if (mapper.TryExtractObjectPropertyIntoCommandLineArgument(o, argument, out mappedKey, out mappedValue))
                    {
                        newCommandLine.Add(mappedKey);
                        newCommandLine.Add(mappedValue);
                    }
                }
            }

            return(newCommandLine.ToArray());
        }
 private void LogLine(string s)
 {
     PowerLogger.LogLine(s);
 }