Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
CoreCommandContext.cs1149 linesDownload Raw Back to namespaces
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System.Collections.ObjectModel;5 6using Dbg = System.Management.Automation;7 8namespace System.Management.Automation9{10    /// <summary>11    /// The context of the core command that is being run. This12    /// includes data like the user name and password, as well13    /// as callbacks for streaming output, prompting, and progress.14    ///15    /// This allows the providers to be called in a variety of situations.16    /// The most common will be from the core cmdlets themselves but they17    /// can also be called programmatically either by having the results18    /// accumulated or by providing delegates for the various streams.19    ///20    /// NOTE:  USER Feedback mechanism are only enabled for the CoreCmdlet21    /// case.  This is because we have not seen a use-case for them in the22    /// other scenarios.23    /// </summary>24    internal sealed class CmdletProviderContext25    {26        #region Trace object27 28        /// <summary>29        /// An instance of the PSTraceSource class used for trace output30        /// using "CmdletProviderContext" as the category.31        /// </summary>32        [Dbg.TraceSource(33             "CmdletProviderContext",34             "The context under which a core command is being run.")]35        private static readonly Dbg.PSTraceSource s_tracer =36            Dbg.PSTraceSource.GetTracer("CmdletProviderContext",37             "The context under which a core command is being run.");38 39        #endregion Trace object40 41        #region Constructor42 43        /// <summary>44        /// Constructs the context under which the core command providers45        /// operate.46        /// </summary>47        /// <param name="executionContext">48        /// The context of the engine.49        /// </param>50        /// <exception cref="ArgumentNullException">51        /// If <paramref name="executionContext"/> is null.52        /// </exception>53        internal CmdletProviderContext(ExecutionContext executionContext)54        {55            if (executionContext == null)56            {57                throw PSTraceSource.NewArgumentNullException(nameof(executionContext));58            }59 60            ExecutionContext = executionContext;61            Origin = CommandOrigin.Internal;62            Drive = executionContext.EngineSessionState.CurrentDrive;63            if ((executionContext.CurrentCommandProcessor != null) &&64                (executionContext.CurrentCommandProcessor.Command is Cmdlet))65            {66                _command = (Cmdlet)executionContext.CurrentCommandProcessor.Command;67            }68        }69 70        /// <summary>71        /// Constructs the context under which the core command providers72        /// operate.73        /// </summary>74        /// <param name="executionContext">75        /// The context of the engine.76        /// </param>77        /// <param name="origin">78        /// The origin of the caller of this API79        /// </param>80        /// <exception cref="ArgumentNullException">81        /// If <paramref name="executionContext"/> is null.82        /// </exception>83        internal CmdletProviderContext(ExecutionContext executionContext, CommandOrigin origin)84        {85            if (executionContext == null)86            {87                throw PSTraceSource.NewArgumentNullException(nameof(executionContext));88            }89 90            ExecutionContext = executionContext;91            Origin = origin;92        }93 94        /// <summary>95        /// Constructs the context under which the core command providers96        /// operate.97        /// </summary>98        /// <param name="command">99        /// The command object that is running.100        /// </param>101        /// <param name="credentials">102        /// The credentials the core command provider should use.103        /// </param>104        /// <param name="drive">105        /// The drive under which this context should operate.106        /// </param>107        /// <exception cref="ArgumentNullException">108        /// If <paramref name="command"/> is null.109        /// </exception>110        /// <exception cref="ArgumentException">111        /// If <paramref name="command"/> contains a null Host or Context reference.112        /// </exception>113        internal CmdletProviderContext(114            PSCmdlet command,115            PSCredential credentials,116            PSDriveInfo drive)117        {118            // verify the command parameter119            if (command == null)120            {121                throw PSTraceSource.NewArgumentNullException(nameof(command));122            }123 124            _command = command;125            Origin = command.CommandOrigin;126 127            if (credentials != null)128            {129                _credentials = credentials;130            }131 132            Drive = drive;133 134            if (command.Host == null)135            {136                throw PSTraceSource.NewArgumentException("command.Host");137            }138 139            if (command.Context == null)140            {141                throw PSTraceSource.NewArgumentException("command.Context");142            }143 144            ExecutionContext = command.Context;145 146            // Stream will default to true because command methods will be used.147 148            PassThru = true;149            _streamErrors = true;150        }151 152        /// <summary>153        /// Constructs the context under which the core command providers154        /// operate.155        /// </summary>156        /// <param name="command">157        /// The command object that is running.158        /// </param>159        /// <param name="credentials">160        /// The credentials the core command provider should use.161        /// </param>162        /// <exception cref="ArgumentNullException">163        /// If <paramref name="command"/> is null.164        /// </exception>165        /// <exception cref="ArgumentException">166        /// If <paramref name="command"/> contains a null Host or Context reference.167        /// </exception>168        internal CmdletProviderContext(169            PSCmdlet command,170            PSCredential credentials)171        {172            // verify the command parameter173            if (command == null)174            {175                throw PSTraceSource.NewArgumentNullException(nameof(command));176            }177 178            _command = command;179            Origin = command.CommandOrigin;180 181            if (credentials != null)182            {183                _credentials = credentials;184            }185 186            if (command.Host == null)187            {188                throw PSTraceSource.NewArgumentException("command.Host");189            }190 191            if (command.Context == null)192            {193                throw PSTraceSource.NewArgumentException("command.Context");194            }195 196            ExecutionContext = command.Context;197 198            // Stream will default to true because command methods will be used.199 200            PassThru = true;201            _streamErrors = true;202        }203 204        /// <summary>205        /// Constructs the context under which the core command providers206        /// operate.207        /// </summary>208        /// <param name="command">209        /// The command object that is running.210        /// </param>211        /// <exception cref="ArgumentNullException">212        /// If <paramref name="command"/> is null.213        /// </exception>214        /// <exception cref="ArgumentException">215        /// If <paramref name="command"/> contains a null Host or Context reference.216        /// </exception>217        internal CmdletProviderContext(218            Cmdlet command)219        {220            // verify the command parameter221            if (command == null)222            {223                throw PSTraceSource.NewArgumentNullException(nameof(command));224            }225 226            _command = command;227            Origin = command.CommandOrigin;228 229            if (command.Context == null)230            {231                throw PSTraceSource.NewArgumentException("command.Context");232            }233 234            ExecutionContext = command.Context;235 236            // Stream will default to true because command methods will be used.237 238            PassThru = true;239            _streamErrors = true;240        }241 242        /// <summary>243        /// Constructs the context under which the core command providers244        /// operate using an existing context.245        /// </summary>246        /// <param name="contextToCopyFrom">247        /// A CmdletProviderContext instance to copy the filters, ExecutionContext,248        /// Credentials, Drive, and Force options from.249        /// </param>250        /// <exception cref="ArgumentNullException">251        /// If <paramref name="contextToCopyFrom"/> is null.252        /// </exception>253        internal CmdletProviderContext(254            CmdletProviderContext contextToCopyFrom)255        {256            if (contextToCopyFrom == null)257            {258                throw PSTraceSource.NewArgumentNullException(nameof(contextToCopyFrom));259            }260 261            ExecutionContext = contextToCopyFrom.ExecutionContext;262 263            _command = contextToCopyFrom._command;264 265            if (contextToCopyFrom.Credential != null)266            {267                _credentials = contextToCopyFrom.Credential;268            }269 270            Drive = contextToCopyFrom.Drive;271            _force = contextToCopyFrom.Force;272            this.CopyFilters(contextToCopyFrom);273            SuppressWildcardExpansion = contextToCopyFrom.SuppressWildcardExpansion;274            DynamicParameters = contextToCopyFrom.DynamicParameters;275            Origin = contextToCopyFrom.Origin;276 277            // Copy the stopping state incase the source context278            // has already been signaled for stopping279 280            Stopping = contextToCopyFrom.Stopping;281 282            // add this context to the stop referral on the copied283            // context284 285            contextToCopyFrom.StopReferrals.Add(this);286            _copiedContext = contextToCopyFrom;287        }288 289        #endregion Constructor290 291        #region private properties292 293        /// <summary>294        /// If the constructor that takes a context to copy is295        /// called, this will be set to the context being copied.296        /// </summary>297        private readonly CmdletProviderContext _copiedContext;298 299        /// <summary>300        /// The credentials under which the operation should run.301        /// </summary>302        private readonly PSCredential _credentials = PSCredential.Empty;303 304        /// <summary>305        /// The force parameter gives guidance to providers on how vigorously they306        /// should try to perform an operation.307        /// </summary>308        private bool _force;309 310        /// <summary>311        /// The command which defines the context. This should not be312        /// made visible to anyone and should only be set through the313        /// constructor.314        /// </summary>315        private readonly Cmdlet _command;316 317        /// <summary>318        /// This makes the origin of the provider request visible to the internals.319        /// </summary>320        internal CommandOrigin Origin { get; } = CommandOrigin.Internal;321 322        /// <summary>323        /// This defines the default behavior for the WriteError method.324        /// If it is true, a call to this method will result in an immediate call325        /// to the command WriteError method, or to the writeErrorDelegate if326        /// one has been supplied.327        /// If it is false, the objects will be accumulated until the328        /// GetErrorObjects method is called.329        /// </summary>330        private readonly bool _streamErrors;331 332        /// <summary>333        /// A collection in which objects that are written using the WriteObject(s)334        /// methods are accumulated if <see cref="PassThru"/> is false.335        /// </summary>336        private Collection<PSObject> _accumulatedObjects = new Collection<PSObject>();337 338        /// <summary>339        /// A collection in which objects that are written using the WriteError340        /// method are accumulated if <see cref="PassThru"/> is false.341        /// </summary>342        private Collection<ErrorRecord> _accumulatedErrorObjects = new Collection<ErrorRecord>();343 344        /// <summary>345        /// The instance of the provider that is currently executing in this context.346        /// </summary>347        private System.Management.Automation.Provider.CmdletProvider _providerInstance;348 349        #endregion private properties350 351        #region Internal properties352 353        /// <summary>354        /// Gets the execution context of the engine.355        /// </summary>356        internal ExecutionContext ExecutionContext { get; }357 358        /// <summary>359        /// Gets or sets the provider instance for the current360        /// execution context.361        /// </summary>362        internal System.Management.Automation.Provider.CmdletProvider ProviderInstance363        {364            get365            {366                return _providerInstance;367            }368 369            set370            {371                _providerInstance = value;372            }373        }374 375        /// <summary>376        /// Copies the include, exclude, and provider filters from377        /// the specified context to this context.378        /// </summary>379        /// <param name="context">380        /// The context to copy the filters from.381        /// </param>382        private void CopyFilters(CmdletProviderContext context)383        {384            Dbg.Diagnostics.Assert(385                context != null,386                "The caller should have verified the context");387 388            Include = context.Include;389            Exclude = context.Exclude;390            Filter = context.Filter;391        }392 393        internal void RemoveStopReferral() => _copiedContext?.StopReferrals.Remove(this);394 395        #endregion Internal properties396 397        #region Public properties398 399        /// <summary>400        /// Gets or sets the dynamic parameters for the context.401        /// </summary>402        internal object DynamicParameters { get; set; }403 404        /// <summary>405        /// Returns MyInvocation from the underlying cmdlet.406        /// </summary>407        internal InvocationInfo MyInvocation408        {409            get410            {411                if (_command != null)412                {413                    return _command.MyInvocation;414                }415                else416                {417                    return null;418                }419            }420        }421 422        /// <summary>423        /// Determines if the Write* calls should be passed through to the command424        /// instance if there is one.  The default value is true.425        /// </summary>426        internal bool PassThru { get; set; }427 428        /// <summary>429        /// The drive associated with this context.430        /// </summary>431        /// <exception cref="ArgumentNullException">432        /// If <paramref name="value"/> is null on set.433        /// </exception>434        internal PSDriveInfo Drive { get; set; }435 436        /// <summary>437        /// Gets the user name under which the operation should run.438        /// </summary>439        internal PSCredential Credential440        {441            get442            {443                PSCredential result = _credentials;444 445                // If the username wasn't specified, use the drive credentials446 447                if (_credentials == null && Drive != null)448                {449                    result = Drive.Credential;450                }451 452                return result;453            }454        }455 456        #region Transaction Support457 458        /// <summary>459        /// Gets the flag that determines if the command requested a transaction.460        /// </summary>461        internal bool UseTransaction462        {463            get464            {465                if ((_command != null) && (_command.CommandRuntime != null))466                {467                    MshCommandRuntime mshRuntime = _command.CommandRuntime as MshCommandRuntime;468 469                    if (mshRuntime != null)470                    {471                        return mshRuntime.UseTransaction;472                    }473                }474 475                return false;476            }477        }478 479        /// <summary>480        /// Returns true if a transaction is available and active.481        /// </summary>482        public bool TransactionAvailable()483        {484            if (_command != null)485            {486                return _command.TransactionAvailable();487            }488 489            return false;490        }491 492        /// <summary>493        /// Gets an object that surfaces the current PowerShell transaction.494        /// When this object is disposed, PowerShell resets the active transaction.495        /// </summary>496        public PSTransactionContext CurrentPSTransaction497        {498            get499            {500                if (_command != null)501                {502                    return _command.CurrentPSTransaction;503                }504 505                return null;506            }507        }508        #endregion Transaction Support509 510        /// <summary>511        /// Gets or sets the Force property that is passed to providers.512        /// </summary>513        internal SwitchParameter Force514        {515            get { return _force; }516 517            set { _force = value; }518        }519 520        /// <summary>521        /// The provider specific filter that should be used when determining522        /// which items an action should take place on.523        /// </summary>524        internal string Filter { get; set; }525 526        /// <summary>527        /// A glob string that signifies which items should be included when determining528        /// which items the action should occur on.529        /// </summary>530        internal Collection<string> Include { get; private set; }531 532        /// <summary>533        /// A glob string that signifies which items should be excluded when determining534        /// which items the action should occur on.535        /// </summary>536        internal Collection<string> Exclude { get; private set; }537 538        /// <summary>539        /// Gets or sets the property that tells providers (that540        /// declare their own wildcard support) to suppress wildcard541        /// expansion. This is set when the user specifies the542        /// -LiteralPath parameter to one of the core commands.543        /// </summary>544        public bool SuppressWildcardExpansion { get; internal set; }545 546        #region User feedback mechanisms547 548        /// <summary>549        /// Confirm the operation with the user.550        /// </summary>551        /// <param name="target">552        /// Name of the target resource being acted upon553        /// </param>554        /// <remarks>true if-and-only-if the action should be performed</remarks>555        /// <exception cref="PipelineStoppedException">556        /// The ActionPreference.Stop or ActionPreference.Inquire policy557        /// triggered a terminating error.  The pipeline failure will be558        /// ActionPreferenceStopException.559        /// Also, this occurs if the pipeline was already stopped.560        /// </exception>561        internal bool ShouldProcess(562            string target)563        {564            bool result = true;565            if (_command != null)566            {567                result = _command.ShouldProcess(target);568            }569 570            return result;571        }572 573        /// <summary>574        /// Confirm the operation with the user.575        /// </summary>576        /// <param name="target">577        /// Name of the target resource being acted upon578        /// </param>579        /// <param name="action">What action was being performed.</param>580        /// <remarks>true if-and-only-if the action should be performed</remarks>581        /// <exception cref="PipelineStoppedException">582        /// The ActionPreference.Stop or ActionPreference.Inquire policy583        /// triggered a terminating error.  The pipeline failure will be584        /// ActionPreferenceStopException.585        /// Also, this occurs if the pipeline was already stopped.586        /// </exception>587        internal bool ShouldProcess(588            string target,589            string action)590        {591            bool result = true;592            if (_command != null)593            {594                result = _command.ShouldProcess(target, action);595            }596 597            return result;598        }599 600        /// <summary>601        /// Confirm the operation with the user.602        /// </summary>603        /// <param name="verboseDescription">604        /// This should contain a textual description of the action to be605        /// performed.  This is what will be displayed to the user for606        /// ActionPreference.Continue.607        /// </param>608        /// <param name="verboseWarning">609        /// This should contain a textual query of whether the action610        /// should be performed, usually in the form of a question.611        /// This is what will be displayed to the user for612        /// ActionPreference.Inquire.613        /// </param>614        /// <param name="caption">615        /// This is the caption of the window which may be displayed616        /// if the user is prompted whether or not to perform the action.617        /// It may be displayed by some hosts, but not all.618        /// </param>619        /// <remarks>true if-and-only-if the action should be performed</remarks>620        /// <exception cref="PipelineStoppedException">621        /// The ActionPreference.Stop or ActionPreference.Inquire policy622        /// triggered a terminating error.  The pipeline failure will be623        /// ActionPreferenceStopException.624        /// Also, this occurs if the pipeline was already stopped.625        /// </exception>626        internal bool ShouldProcess(627            string verboseDescription,628            string verboseWarning,629            string caption)630        {631            bool result = true;632            if (_command != null)633            {634                result = _command.ShouldProcess(635                    verboseDescription,636                    verboseWarning,637                    caption);638            }639 640            return result;641        }642 643        /// <summary>644        /// Confirm the operation with the user.645        /// </summary>646        /// <param name="verboseDescription">647        /// This should contain a textual description of the action to be648        /// performed.  This is what will be displayed to the user for649        /// ActionPreference.Continue.650        /// </param>651        /// <param name="verboseWarning">652        /// This should contain a textual query of whether the action653        /// should be performed, usually in the form of a question.654        /// This is what will be displayed to the user for655        /// ActionPreference.Inquire.656        /// </param>657        /// <param name="caption">658        /// This is the caption of the window which may be displayed659        /// if the user is prompted whether or not to perform the action.660        /// It may be displayed by some hosts, but not all.661        /// </param>662        /// <param name="shouldProcessReason">663        /// Indicates the reason(s) why ShouldProcess returned what it returned.664        /// Only the reasons enumerated in665        /// <see cref="System.Management.Automation.ShouldProcessReason"/>666        /// are returned.667        /// </param>668        /// <remarks>true if-and-only-if the action should be performed</remarks>669        /// <exception cref="PipelineStoppedException">670        /// The ActionPreference.Stop or ActionPreference.Inquire policy671        /// triggered a terminating error.  The pipeline failure will be672        /// ActionPreferenceStopException.673        /// Also, this occurs if the pipeline was already stopped.674        /// </exception>675        internal bool ShouldProcess(676            string verboseDescription,677            string verboseWarning,678            string caption,679            out ShouldProcessReason shouldProcessReason)680        {681            bool result = true;682            if (_command != null)683            {684                result = _command.ShouldProcess(685                    verboseDescription,686                    verboseWarning,687                    caption,688                    out shouldProcessReason);689            }690            else691            {692                shouldProcessReason = ShouldProcessReason.None;693            }694 695            return result;696        }697 698        /// <summary>699        /// Ask the user whether to continue/stop or break to a subshell.700        /// </summary>701        /// <param name="query">702        /// Message to display to the user. This routine will append703        /// the text "Continue" to ensure that people know what question704        /// they are answering.705        /// </param>706        /// <param name="caption">707        /// Dialog caption if the host uses a dialog.708        /// </param>709        /// <returns>710        /// True if the user wants to continue, false if not.711        /// </returns>712        internal bool ShouldContinue(713            string query,714            string caption)715        {716            bool result = true;717            if (_command != null)718            {719                result = _command.ShouldContinue(query, caption);720            }721 722            return result;723        }724 725        /// <summary>726        /// Ask the user whether to continue/stop or break to a subshell.727        /// </summary>728        /// <param name="query">729        /// Message to display to the user. This routine will append730        /// the text "Continue" to ensure that people know what question731        /// they are answering.732        /// </param>733        /// <param name="caption">734        /// Dialog caption if the host uses a dialog.735        /// </param>736        /// <param name="yesToAll">737        /// Indicates whether the user selected YesToAll738        /// </param>739        /// <param name="noToAll">740        /// Indicates whether the user selected NoToAll741        /// </param>742        /// <returns>743        /// True if the user wants to continue, false if not.744        /// </returns>745        internal bool ShouldContinue(746            string query,747            string caption,748            ref bool yesToAll,749            ref bool noToAll)750        {751            bool result = true;752            if (_command != null)753            {754                result = _command.ShouldContinue(755                    query, caption, ref yesToAll, ref noToAll);756            }757            else758            {759                yesToAll = false;760                noToAll = false;761            }762 763            return result;764        }765 766        /// <summary>767        /// Writes the object to the Verbose pipe.768        /// </summary>769        /// <param name="text">770        /// The string that needs to be written.771        /// </param>772        internal void WriteVerbose(string text) => _command?.WriteVerbose(text);773 774        /// <summary>775        /// Writes the object to the Warning pipe.776        /// </summary>777        /// <param name="text">778        /// The string that needs to be written.779        /// </param>780        internal void WriteWarning(string text) => _command?.WriteWarning(text);781 782        internal void WriteProgress(ProgressRecord record) => _command?.WriteProgress(record);783 784        /// <summary>785        /// Writes a debug string.786        /// </summary>787        /// <param name="text">788        /// The String that needs to be written.789        /// </param>790        internal void WriteDebug(string text) => _command?.WriteDebug(text);791 792        internal void WriteInformation(InformationRecord record) => _command?.WriteInformation(record);793 794        internal void WriteInformation(object messageData, string[] tags) => _command?.WriteInformation(messageData, tags);795 796        #endregion User feedback mechanisms797 798        #endregion Public properties799 800        #region Public methods801 802        /// <summary>803        /// Sets the filters that are used within this context.804        /// </summary>805        /// <param name="include">806        /// The include filters which determines which items are included in807        /// operations within this context.808        /// </param>809        /// <param name="exclude">810        /// The exclude filters which determines which items are excluded from811        /// operations within this context.812        /// </param>813        /// <param name="filter">814        /// The provider specific filter for the operation.815        /// </param>816        internal void SetFilters(Collection<string> include, Collection<string> exclude, string filter)817        {818            Include = include;819            Exclude = exclude;820            Filter = filter;821        }822 823        /// <summary>824        /// Gets an array of the objects that have been accumulated825        /// and the clears the collection.826        /// </summary>827        /// <returns>828        /// An object array of the objects that have been accumulated829        /// through the WriteObject method.830        /// </returns>831        internal Collection<PSObject> GetAccumulatedObjects()832        {833            // Get the contents as an array834 835            Collection<PSObject> results = _accumulatedObjects;836            _accumulatedObjects = new Collection<PSObject>();837 838            // Return the array839 840            return results;841        }842 843        /// <summary>844        /// Gets an array of the error objects that have been accumulated845        /// and the clears the collection.846        /// </summary>847        /// <returns>848        /// An object array of the objects that have been accumulated849        /// through the WriteError method.850        /// </returns>851        internal Collection<ErrorRecord> GetAccumulatedErrorObjects()852        {853            // Get the contents as an array854 855            Collection<ErrorRecord> results = _accumulatedErrorObjects;856            _accumulatedErrorObjects = new Collection<ErrorRecord>();857 858            // Return the array859 860            return results;861        }862 863        /// <summary>864        /// If there are any errors accumulated, the first error is thrown.865        /// </summary>866        /// <exception cref="ProviderInvocationException">867        /// If a CmdletProvider wrote any exceptions to the error pipeline, it is868        /// wrapped and then thrown.869        /// </exception>870        internal void ThrowFirstErrorOrDoNothing()871        {872            ThrowFirstErrorOrDoNothing(true);873        }874 875        /// <summary>876        /// If there are any errors accumulated, the first error is thrown.877        /// </summary>878        /// <param name="wrapExceptionInProviderException">879        /// If true, the error will be wrapped in a ProviderInvocationException before880        /// being thrown. If false, the error will be thrown as is.881        /// </param>882        /// <exception cref="ProviderInvocationException">883        /// If <paramref name="wrapExceptionInProviderException"/> is true, the884        /// first exception that was written to the error pipeline by a CmdletProvider885        /// is wrapped and thrown.886        /// </exception>887        /// <exception>888        /// If <paramref name="wrapExceptionInProviderException"/> is false,889        /// the first exception that was written to the error pipeline by a CmdletProvider890        /// is thrown.891        /// </exception>892        internal void ThrowFirstErrorOrDoNothing(bool wrapExceptionInProviderException)893        {894            if (HasErrors())895            {896                Collection<ErrorRecord> errors = GetAccumulatedErrorObjects();897 898                if (errors != null && errors.Count > 0)899                {900                    // Throw the first exception901 902                    if (wrapExceptionInProviderException)903                    {904                        ProviderInfo providerInfo = null;905                        if (this.ProviderInstance != null)906                        {907                            providerInfo = this.ProviderInstance.ProviderInfo;908                        }909 910                        ProviderInvocationException e =911                            new ProviderInvocationException(912                                providerInfo,913                                errors[0]);914 915                        // Log a provider health event916 917                        MshLog.LogProviderHealthEvent(918                            this.ExecutionContext,919                            providerInfo != null ? providerInfo.Name : "unknown provider",920                            e,921                            Severity.Warning);922 923                        throw e;924                    }925                    else926                    {927                        throw errors[0].Exception;928                    }929                }930            }931        }932 933        /// <summary>934        /// Writes all the accumulated errors to the specified context using WriteError.935        /// </summary>936        /// <param name="errorContext">937        /// The context to write the errors to.938        /// </param>939        /// <exception cref="ArgumentNullException">940        /// If <paramref name="errorContext"/> is null.941        /// </exception>942        internal void WriteErrorsToContext(CmdletProviderContext errorContext)943        {944            if (errorContext == null)945            {946                throw PSTraceSource.NewArgumentNullException(nameof(errorContext));947            }948 949            if (HasErrors())950            {951                foreach (ErrorRecord errorRecord in GetAccumulatedErrorObjects())952                {953                    errorContext.WriteError(errorRecord);954                }955            }956        }957 958        /// <summary>959        /// Writes an object to the output.960        /// </summary>961        /// <param name="obj">962        /// The object to be written.963        /// </param>964        /// <remarks>965        /// If streaming is on and the writeObjectHandler was specified then the object966        /// gets written to the writeObjectHandler. If streaming is on and the writeObjectHandler967        /// was not specified and the command object was specified, the object gets written to968        /// the WriteObject method of the command object.969        /// If streaming is off the object gets written to an accumulator collection. The collection970        /// of written object can be retrieved using the AccumulatedObjects method.971        /// </remarks>972        /// <exception cref="InvalidOperationException">973        /// The CmdletProvider could not stream the results because no974        /// cmdlet was specified to stream the output through.975        /// </exception>976        /// <exception cref="PipelineStoppedException">977        /// If the pipeline has been signaled for stopping but978        /// the provider calls this method.979        /// </exception>980        internal void WriteObject(object obj)981        {982            // Making sure to obey the StopProcessing by983            // throwing an exception anytime a provider tries984            // to WriteObject985 986            if (Stopping)987            {988                PipelineStoppedException stopPipeline =989                    new PipelineStoppedException();990 991                throw stopPipeline;992            }993 994            if (PassThru)995            {996                if (_command != null)997                {998                    s_tracer.WriteLine("Writing to command pipeline");999 1000                    // Since there was no writeObject handler use1001                    // the command WriteObject method.1002 1003                    _command.WriteObject(obj);1004                }1005                else1006                {1007                    // The flag was set for streaming but we have no where1008                    // to stream to.1009 1010                    InvalidOperationException e =1011                        PSTraceSource.NewInvalidOperationException(1012                            SessionStateStrings.OutputStreamingNotEnabled);1013                    throw e;1014                }1015            }1016            else1017            {1018                s_tracer.WriteLine("Writing to accumulated objects");1019 1020                // Convert the object to a PSObject if it's not already1021                // one.1022 1023                PSObject newObj = PSObject.AsPSObject(obj);1024 1025                // Since we are not streaming, just add the object to the accumulatedObjects1026 1027                _accumulatedObjects.Add(newObj);1028            }1029        }1030 1031        /// <summary>1032        /// Writes the error to the pipeline or accumulates the error in an internal1033        /// buffer.1034        /// </summary>1035        /// <param name="errorRecord">1036        /// The error record to write to the pipeline or the internal buffer.1037        /// </param>1038        /// <exception cref="InvalidOperationException">1039        /// The CmdletProvider could not stream the error because no1040        /// cmdlet was specified to stream the output through.1041        /// </exception>1042        /// <exception cref="PipelineStoppedException">1043        /// If the pipeline has been signaled for stopping but1044        /// the provider calls this method.1045        /// </exception>1046        internal void WriteError(ErrorRecord errorRecord)1047        {1048            // Making sure to obey the StopProcessing by1049            // throwing an exception anytime a provider tries1050            // to WriteError1051 1052            if (Stopping)1053            {1054                PipelineStoppedException stopPipeline =1055                    new PipelineStoppedException();1056 1057                throw stopPipeline;1058            }1059 1060            if (_streamErrors)1061            {1062                if (_command != null)1063                {1064                    s_tracer.WriteLine("Writing error package to command error pipe");1065 1066                    _command.WriteError(errorRecord);1067                }1068                else1069                {1070                    InvalidOperationException e =1071                        PSTraceSource.NewInvalidOperationException(1072                            SessionStateStrings.ErrorStreamingNotEnabled);1073                    throw e;1074                }1075            }1076            else1077            {1078                // Since we are not streaming, just add the object to the accumulatedErrorObjects1079                _accumulatedErrorObjects.Add(errorRecord);1080 1081                if (errorRecord.ErrorDetails != null1082                    && errorRecord.ErrorDetails.TextLookupError != null)1083                {1084                    Exception textLookupError = errorRecord.ErrorDetails.TextLookupError;1085                    errorRecord.ErrorDetails.TextLookupError = null;1086                    MshLog.LogProviderHealthEvent(1087                        this.ExecutionContext,1088                        this.ProviderInstance.ProviderInfo.Name,1089                        textLookupError,1090                        Severity.Warning);1091                }1092            }1093        }1094 1095        /// <summary>1096        /// If the error pipeline hasn't been supplied a delegate or a command then this method1097        /// will determine if any errors have accumulated.1098        /// </summary>1099        /// <returns>1100        /// True if the errors are being accumulated and some errors have been accumulated.  False otherwise.1101        /// </returns>1102        internal bool HasErrors()1103        {1104            return _accumulatedErrorObjects != null && _accumulatedErrorObjects.Count > 0;1105        }1106 1107        /// <summary>1108        /// Call this on a separate thread when a provider is using1109        /// this context to do work. This method will call the StopProcessing1110        /// method of the provider.1111        /// </summary>1112        internal void StopProcessing()1113        {1114            Stopping = true;1115 1116            // We don't need to catch any of the exceptions here because1117            // we are terminating the pipeline and any exception will1118            // be caught by the engine.1119            _providerInstance?.StopProcessing();1120 1121            // Call the stop referrals if any1122 1123            foreach (CmdletProviderContext referralContext in StopReferrals)1124            {1125                referralContext.StopProcessing();1126            }1127        }1128 1129        internal bool Stopping { get; private set; }1130 1131        /// <summary>1132        /// The list of contexts to which the StopProcessing calls1133        /// should be referred.1134        /// </summary>1135        internal Collection<CmdletProviderContext> StopReferrals { get; } = new Collection<CmdletProviderContext>();1136 1137        internal bool HasIncludeOrExclude1138        {1139            get1140            {1141                return ((Include != null && Include.Count > 0) ||1142                        (Exclude != null && Exclude.Count > 0));1143            }1144        }1145 1146        #endregion Public methods1147    }1148}1149