Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
OutputManager.cs328 linesDownload Raw Back to common
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System;5using System.Collections.Generic;6using System.Collections.Specialized;7using System.Management.Automation;8using System.Management.Automation.Internal;9 10namespace Microsoft.PowerShell.Commands.Internal.Format11{12    /// <summary>13    /// Inner command class used to manage the sub pipelines14    /// it determines which command should process the incoming objects15    /// based on the object type16    ///17    /// This class is the implementation class for out-console and out-file.18    /// </summary>19    internal sealed class OutputManagerInner : ImplementationCommandBase20    {21        #region tracer22        [TraceSource("format_out_OutputManagerInner", "OutputManagerInner")]23        internal static readonly PSTraceSource tracer = PSTraceSource.GetTracer("format_out_OutputManagerInner", "OutputManagerInner");24        #endregion tracer25 26        #region LineOutput27        internal LineOutput LineOutput28        {29            set30            {31                lock (_syncRoot)32                {33                    _lo = value;34 35                    if (_isStopped)36                    {37                        _lo.StopProcessing();38                    }39                }40            }41        }42 43        private LineOutput _lo = null;44        #endregion45 46        /// <summary>47        /// Handler for processing each object coming through the pipeline48        /// it forwards the call to the pipeline manager object.49        /// </summary>50        internal override void ProcessRecord()51        {52            PSObject so = this.ReadObject();53 54            if (so == null || so == AutomationNull.Value)55            {56                return;57            }58 59            // on demand initialization when the first pipeline60            // object is initialized61            if (_mgr == null)62            {63                _mgr = new SubPipelineManager();64                _mgr.Initialize(_lo, this.OuterCmdlet().Context);65            }66 67#if false68            // if the object supports IEnumerable,69            // unpack the object and process each member separately70            IEnumerable e = PSObjectHelper.GetEnumerable (so);71 72            if (e == null)73            {74                this.mgr.Process (so);75            }76            else77            {78                foreach (object obj in e)79                {80                    this.mgr.Process (PSObjectHelper.AsPSObject (obj));81                }82            }83#else84            _mgr.Process(so);85#endif86        }87 88        /// <summary>89        /// Handler for processing shut down. It forwards the call to the90        /// pipeline manager object.91        /// </summary>92        internal override void EndProcessing()93        {94            // shut down only if we ever processed a pipeline object95            _mgr?.ShutDown();96        }97 98        internal override void StopProcessing()99        {100            lock (_syncRoot)101            {102                _lo?.StopProcessing();103                _isStopped = true;104            }105        }106 107        /// <summary>108        /// Make sure we dispose of the sub pipeline manager.109        /// </summary>110        protected override void InternalDispose()111        {112            base.InternalDispose();113            if (_mgr != null)114            {115                _mgr.Dispose();116                _mgr = null;117            }118        }119 120        /// <summary>121        /// Instance of the pipeline manager object.122        /// </summary>123        private SubPipelineManager _mgr = null;124 125        /// <summary>126        /// True if the cmdlet has been stopped.127        /// </summary>128        private bool _isStopped = false;129 130        /// <summary>131        /// Lock object.132        /// </summary>133        private readonly object _syncRoot = new object();134    }135 136    /// <summary>137    /// Object managing the sub-pipelines that execute138    /// different output commands (or different instances of the139    /// default one)140    /// </summary>141    internal sealed class SubPipelineManager : IDisposable142    {143        /// <summary>144        /// Entry defining a command to be run in a separate pipeline.145        /// </summary>146        private sealed class CommandEntry : IDisposable147        {148            /// <summary>149            /// Instance of pipeline wrapper object.150            /// </summary>151            internal CommandWrapper command = new CommandWrapper();152 153            /// <summary>154            /// </summary>155            /// <param name="typeName">ETS type name of the object to process.</param>156            /// <returns>True if there is a match.</returns>157            internal bool AppliesToType(string typeName)158            {159                foreach (string s in _applicableTypes)160                {161                    if (string.Equals(s, typeName, StringComparison.OrdinalIgnoreCase))162                        return true;163                }164 165                return false;166            }167 168            /// <summary>169            /// Just dispose of the inner command wrapper.170            /// </summary>171            public void Dispose()172            {173                if (this.command == null)174                    return;175 176                this.command.Dispose();177                this.command = null;178            }179 180            /// <summary>181            /// Ordered list of ETS type names this object is handling.182            /// </summary>183            private readonly StringCollection _applicableTypes = new StringCollection();184        }185 186        /// <summary>187        /// Initialize the pipeline manager before any object is processed.188        /// </summary>189        /// <param name="lineOutput">LineOutput to pass to the child pipelines.</param>190        /// <param name="context">ExecutionContext to pass to the child pipelines.</param>191        internal void Initialize(LineOutput lineOutput, ExecutionContext context)192        {193            _lo = lineOutput;194            InitializeCommandsHardWired(context);195        }196 197        /// <summary>198        /// Hard wired registration helper for specialized types.199        /// </summary>200        /// <param name="context">ExecutionContext to pass to the child pipeline.</param>201        private void InitializeCommandsHardWired(ExecutionContext context)202        {203            // set the default handler204            RegisterCommandDefault(context, "out-lineoutput", typeof(OutLineOutputCommand));205            /*206            NOTE:207            This is the spot where we could add new specialized handlers for208            additional types. Adding a handler here would cause a new sub-pipeline209            to be created.210 211            For example, the following line would add a new handler named "out-example"212            to be invoked when the incoming object type is "MyNamespace.Whatever.Example"213 214            RegisterCommandForTypes (context, "out-example", new string[] { "MyNamespace.Whatever.Example" });215 216            And the method can be like this:217            private void RegisterCommandForTypes (ExecutionContext context, string commandName, Type commandType, string[] types)218            {219                CommandEntry ce = new CommandEntry ();220 221                ce.command.Initialize (context, commandName, commandType);222                ce.command.AddNamedParameter ("LineOutput", this.lo);223                for (int k = 0; k < types.Length; k++)224                {225                    ce.AddApplicableType (types[k]);226                }227 228                this.commandEntryList.Add (ce);229            }230            */231        }232 233        /// <summary>234        /// Register the default output command.235        /// </summary>236        /// <param name="context">ExecutionContext to pass to the child pipeline.</param>237        /// <param name="commandName">Name of the command to execute.</param>238        /// <param name="commandType">Type of the command to execute.</param>239        private void RegisterCommandDefault(ExecutionContext context, string commandName, Type commandType)240        {241            CommandEntry ce = new CommandEntry();242 243            ce.command.Initialize(context, commandName, commandType);244            ce.command.AddNamedParameter("LineOutput", _lo);245            _defaultCommandEntry = ce;246        }247 248        /// <summary>249        /// Process an incoming parent pipeline object.250        /// </summary>251        /// <param name="so">Pipeline object to process.</param>252        internal void Process(PSObject so)253        {254            // select which pipeline should handle the object255            CommandEntry ce = this.GetActiveCommandEntry(so);256 257            Diagnostics.Assert(ce != null, "CommandEntry ce must not be null");258 259            // delegate the processing260            ce.command.Process(so);261        }262 263        /// <summary>264        /// Shut down the child pipelines.265        /// </summary>266        internal void ShutDown()267        {268            // we assume that command entries are never null269            foreach (CommandEntry ce in _commandEntryList)270            {271                Diagnostics.Assert(ce != null, "ce != null");272                ce.command.ShutDown();273                ce.command = null;274            }275 276            // we assume we always have a default command entry277            Diagnostics.Assert(_defaultCommandEntry != null, "defaultCommandEntry != null");278            _defaultCommandEntry.command.ShutDown();279            _defaultCommandEntry.command = null;280        }281 282        public void Dispose()283        {284            // we assume that command entries are never null285            foreach (CommandEntry ce in _commandEntryList)286            {287                Diagnostics.Assert(ce != null, "ce != null");288                ce.Dispose();289            }290 291            // we assume we always have a default command entry292            Diagnostics.Assert(_defaultCommandEntry != null, "defaultCommandEntry != null");293            _defaultCommandEntry.Dispose();294        }295 296        /// <summary>297        /// It selects the applicable out command (it can be the default one)298        /// to process the current pipeline object.299        /// </summary>300        /// <param name="so">Pipeline object to be processed.</param>301        /// <returns>Applicable command entry.</returns>302        private CommandEntry GetActiveCommandEntry(PSObject so)303        {304            string typeName = PSObjectHelper.PSObjectIsOfExactType(so.InternalTypeNames);305            foreach (CommandEntry ce in _commandEntryList)306            {307                if (ce.AppliesToType(typeName))308                    return ce;309            }310 311            // failed any match: return the default handler312            return _defaultCommandEntry;313        }314 315        private LineOutput _lo = null;316 317        /// <summary>318        /// List of command entries, each with a set of applicable types.319        /// </summary>320        private readonly List<CommandEntry> _commandEntryList = new List<CommandEntry>();321 322        /// <summary>323        /// Default command entry to be executed when all type matches fail.324        /// </summary>325        private CommandEntry _defaultCommandEntry = new CommandEntry();326    }327}328