Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes308downloads
MshCommandRuntime.cs3830 linesDownload Raw Back to engine
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4#pragma warning disable 1634, 16915 6using System.Collections;7using System.Collections.Generic;8using System.Collections.ObjectModel;9using System.Management.Automation.Host;10using System.Management.Automation.Internal;11using System.Management.Automation.Internal.Host;12using System.Management.Automation.Remoting;13using System.Management.Automation.Runspaces;14using System.Threading;15 16using Dbg = System.Management.Automation.Diagnostics;17 18namespace System.Management.Automation19{20    /// <summary>21    /// Monad internal implementation of the ICommandRuntime2 interface22    /// used for execution in the monad engine environment.23    ///24    /// There will be one instance of this class for each cmdlet added to25    /// a pipeline. When the cmdlet calls its WriteObject API, that API will call26    /// the WriteObject implementation in this class which, in turn, calls27    /// the downstream cmdlet.28    /// </summary>29    internal class MshCommandRuntime : ICommandRuntime230    {31        #region private_members32 33        /// <summary>34        /// Gets/Set the execution context value for this runtime object.35        /// </summary>36        internal ExecutionContext Context { get; set; }37 38        private SessionState _state = null;39        internal InternalHost CBhost;40 41        /// <summary>42        /// The host object for this object.43        /// </summary>44        public PSHost Host { get; }45 46        // Output pipes.47        private Pipe _inputPipe;48        private Pipe _outputPipe;49        private Pipe _errorOutputPipe;50 51        /// <summary>52        /// IsClosed indicates to the Cmdlet whether its upstream partner53        /// could still write more data to its incoming queue.54        /// Note that there may still be data in the incoming queue.55        /// </summary>56        internal bool IsClosed { get; set; }57 58        /// <summary>59        /// True if we're not closed and the input pipe is non-null...60        /// </summary>61        internal bool IsPipelineInputExpected62        {63            get64            {65                // No objects in the input pipe66                // The pipe is closed. So there can't be any more object67                if (IsClosed && (_inputPipe == null || _inputPipe.Empty))68                {69                    return false;70                }71 72                return true;73            }74        }75 76        /// <summary>77        /// This allows all success output to be set to a variable.  Similar to the way -errorvariable sets78        /// all errors to a variable name.  Semantically this is equivalent to :  cmd |set-var varname -passthru79        /// but it should be MUCH faster as there is no binding that takes place.80        /// </summary>81        /// <exception cref="System.ArgumentNullException">82        /// may not be set to null83        /// </exception>84        /// <remarks>85        /// This is a common parameter via class CommonParameters.86        /// </remarks>87        internal string OutVariable { get; set; }88 89        internal IList OutVarList { get { return _outVarList; } set { _outVarList = value; } }90 91        private IList _outVarList = null;92 93        internal PipelineProcessor PipelineProcessor { get; set; }94 95        private readonly CommandInfo _commandInfo;96        private readonly InternalCommand _thisCommand;97 98        #endregion private_members99 100        internal MshCommandRuntime(ExecutionContext context, CommandInfo commandInfo, InternalCommand thisCommand)101        {102            Context = context;103            Host = context.EngineHostInterface;104            this.CBhost = (InternalHost)context.EngineHostInterface;105            _commandInfo = commandInfo;106            _thisCommand = thisCommand;107            LogPipelineExecutionDetail = InitShouldLogPipelineExecutionDetail();108        }109 110        /// <summary>111        /// For diagnostic purposes.112        /// </summary>113        /// <returns></returns>114        public override string ToString()115        {116            if (_commandInfo != null)117                return _commandInfo.ToString();118            return "<NullCommandInfo>"; // does not require localization119        }120 121        private InvocationInfo _myInvocation;122        /// <summary>123        /// Return the invocation data object for this command.124        /// </summary>125        /// <value>The invocation object for this command.</value>126        internal InvocationInfo MyInvocation127        {128            get { return _myInvocation ??= _thisCommand.MyInvocation; }129        }130 131        /// <summary>132        /// Internal helper. Indicates whether stop has been requested on this command.133        /// </summary>134        internal bool IsStopping135        {136            get { return (this.PipelineProcessor != null && this.PipelineProcessor.Stopping); }137        }138 139        #region Write140 141        // Trust: WriteObject needs to respect EmitTrustCategory142 143        /// <summary>144        /// Writes the object to the output pipe.145        /// </summary>146        /// <param name="sendToPipeline">147        /// The object that needs to be written.  This will be written as148        /// a single object, even if it is an enumeration.149        /// </param>150        /// <exception cref="System.Management.Automation.PipelineStoppedException">151        /// The pipeline has already been terminated, or was terminated152        /// during the execution of this method.153        /// The Cmdlet should generally just allow PipelineStoppedException154        /// to percolate up to the caller of ProcessRecord etc.155        /// </exception>156        /// <exception cref="System.InvalidOperationException">157        /// Not permitted at this time or from this thread.158        /// WriteObject may only be called during a call to this Cmdlet's159        /// implementation of ProcessRecord, BeginProcessing or EndProcessing,160        /// and only from that thread.161        /// </exception>162        /// <seealso cref="System.Management.Automation.ICommandRuntime.WriteObject(object,bool)"/>163        /// <seealso cref="System.Management.Automation.ICommandRuntime.WriteError(ErrorRecord)"/>164        public void WriteObject(object sendToPipeline)165        {166            // This check will be repeated in _WriteObjectSkipAllowCheck,167            // but we want PipelineStoppedException to take precedence168            // over InvalidOperationException if the pipeline has been169            // closed.170            ThrowIfStopping();171 172#if CORECLR173            // SecurityContext is not supported in CoreCLR174            DoWriteObject(sendToPipeline);175#else176            if (UseSecurityContextRun)177            {178                if (PipelineProcessor == null || PipelineProcessor.SecurityContext == null)179                    throw PSTraceSource.NewInvalidOperationException(PipelineStrings.WriteNotPermitted);180                ContextCallback delegateCallback =181                    new ContextCallback(DoWriteObject);182 183                SecurityContext.Run(184                    PipelineProcessor.SecurityContext.CreateCopy(),185                    delegateCallback,186                    sendToPipeline);187            }188            else189            {190                DoWriteObject(sendToPipeline);191            }192#endif193        }194 195        /// <exception cref="System.Management.Automation.PipelineStoppedException">196        /// The pipeline has already been terminated, or was terminated197        /// during the execution of this method.198        /// The Cmdlet should generally just allow PipelineStoppedException199        /// to percolate up to the caller of ProcessRecord etc.200        /// </exception>201        /// <exception cref="System.InvalidOperationException">202        /// Not permitted at this time or from this thread203        /// </exception>204        private void DoWriteObject(object sendToPipeline)205        {206            ThrowIfWriteNotPermitted(true);207            _WriteObjectSkipAllowCheck(sendToPipeline);208        }209 210        /// <summary>211        /// Writes one or more objects to the output pipe.212        /// If the object is a collection and the enumerateCollection flag213        /// is true, the objects in the collection214        /// will be written individually.215        /// </summary>216        /// <param name="sendToPipeline">217        /// The object that needs to be written to the pipeline.218        /// </param>219        /// <param name="enumerateCollection">220        /// true if the collection should be enumerated221        /// </param>222        /// <exception cref="System.Management.Automation.PipelineStoppedException">223        /// The pipeline has already been terminated, or was terminated224        /// during the execution of this method.225        /// The Cmdlet should generally just allow PipelineStoppedException226        /// to percolate up to the caller of ProcessRecord etc.227        /// </exception>228        /// <exception cref="System.InvalidOperationException">229        /// Not permitted at this time or from this thread.230        /// WriteObject may only be called during a call to this Cmdlet's231        /// implementation of ProcessRecord, BeginProcessing or EndProcessing,232        /// and only from that thread.233        /// </exception>234        /// <seealso cref="System.Management.Automation.ICommandRuntime.WriteObject(object)"/>235        /// <seealso cref="System.Management.Automation.ICommandRuntime.WriteError(ErrorRecord)"/>236        public void WriteObject(object sendToPipeline, bool enumerateCollection)237        {238            if (!enumerateCollection)239            {240                WriteObject(sendToPipeline);241                return;242            }243 244            // This check will be repeated in _WriteObjectsSkipAllowCheck,245            // but we want PipelineStoppedException to take precedence246            // over InvalidOperationException if the pipeline has been247            // closed.248            ThrowIfStopping();249 250#if CORECLR251            // SecurityContext is not supported in CoreCLR252            DoWriteEnumeratedObject(sendToPipeline);253#else254            if (UseSecurityContextRun)255            {256                if (PipelineProcessor == null || PipelineProcessor.SecurityContext == null)257                    throw PSTraceSource.NewInvalidOperationException(PipelineStrings.WriteNotPermitted);258                ContextCallback delegateCallback =259                    new ContextCallback(DoWriteObjects);260                SecurityContext.Run(261                    PipelineProcessor.SecurityContext.CreateCopy(),262                    delegateCallback,263                    sendToPipeline);264            }265            else266            {267                DoWriteObjects(sendToPipeline);268            }269#endif270        }271 272        /// <summary>273        /// Writes an object enumerated from a collection to the output pipe.274        /// </summary>275        /// <param name="sendToPipeline">276        /// The enumerated object that needs to be written to the pipeline.277        /// </param>278        /// <exception cref="System.Management.Automation.PipelineStoppedException">279        /// The pipeline has already been terminated, or was terminated280        /// during the execution of this method.281        /// The Cmdlet should generally just allow PipelineStoppedException282        /// to percolate up to the caller of ProcessRecord etc.283        /// </exception>284        /// <exception cref="System.InvalidOperationException">285        /// Not permitted at this time or from this thread.286        /// </exception>287        private void DoWriteEnumeratedObject(object sendToPipeline)288        {289            // NOTICE-2004/06/08-JonN 959638290            ThrowIfWriteNotPermitted(true);291            _EnumerateAndWriteObjectSkipAllowCheck(sendToPipeline);292        }293        // Trust:  public void WriteObject(object sendToPipeline, DataTrustCategory trustCategory);     // enumerateCollection defaults to false294        // Trust:  public void WriteObject(object sendToPipeline, bool enumerateCollection, DataTrustCategory trustCategory);295 296        // Variables needed to generate a unique SourceId for297        // WriteProgress(ProgressRecord).298        private static Int64 s_lastUsedSourceId /* = 0 */;299        private Int64 _sourceId /* = 0 */;300 301        /// <summary>302        /// Display progress information.303        /// </summary>304        /// <param name="progressRecord">Progress information.</param>305        /// <exception cref="System.Management.Automation.PipelineStoppedException">306        /// The pipeline has already been terminated, or was terminated307        /// during the execution of this method.308        /// The Cmdlet should generally just allow PipelineStoppedException309        /// to percolate up to the caller of ProcessRecord etc.310        /// </exception>311        /// <exception cref="System.InvalidOperationException">312        /// Not permitted at this time or from this thread.313        /// WriteProgress may only be called during a call to this Cmdlet's314        /// implementation of ProcessRecord, BeginProcessing or EndProcessing,315        /// and only from that thread.316        /// </exception>317        /// <remarks>318        /// Use WriteProgress to display progress information about319        /// the activity of your Cmdlet, when the operation of your Cmdlet320        /// could potentially take a long time.321        ///322        /// By default, progress output will323        /// be displayed, although this can be configured with the324        /// ProgressPreference shell variable.325        /// </remarks>326        /// <seealso cref="System.Management.Automation.Cmdlet.WriteDebug(string)"/>327        /// <seealso cref="System.Management.Automation.Cmdlet.WriteWarning(string)"/>328        /// <seealso cref="System.Management.Automation.Cmdlet.WriteVerbose(string)"/>329        public void WriteProgress(ProgressRecord progressRecord)330        {331            this.WriteProgress(progressRecord, false);332        }333 334        internal void WriteProgress(ProgressRecord progressRecord, bool overrideInquire)335        {336            // NTRAID#Windows Out Of Band Releases-918023-2005/08/22-JonN337            ThrowIfStopping();338 339            //340            // WriteError/WriteObject have a check that prevents them to be called from outside341            // Begin/Process/End. This is done because the Pipeline needs to be ready before these342            // functions can be called.343            //344            // WriteDebug/Warning/Verbose/Process used to do the same check, even though it is not345            // strictly needed. If we ever implement pipelines for these objects we may need to346            // enforce the check again.347            //348            // See bug 583774 in the Windows 7 database for more details.349            //350            ThrowIfWriteNotPermitted(false);351 352            // Bug909439: We need a unique sourceId to send to353            // WriteProgress. The following logic ensures that354            // there is a unique id for each Cmdlet instance.355 356            if (_sourceId == 0)357            {358                _sourceId = Interlocked.Increment(ref s_lastUsedSourceId);359            }360 361            this.WriteProgress(_sourceId, progressRecord, overrideInquire);362        }363 364        /// <summary>365        /// Displays progress output if enabled.366        /// </summary>367        /// <param name="sourceId">368        /// Identifies which command is reporting progress369        /// </param>370        /// <param name="progressRecord">371        /// Progress status to be displayed372        /// </param>373        /// <exception cref="System.Management.Automation.PipelineStoppedException">374        /// The pipeline has already been terminated, or was terminated375        /// during the execution of this method.376        /// The Cmdlet should generally just allow PipelineStoppedException377        /// to percolate up to the caller of ProcessRecord etc.378        /// </exception>379        /// <remarks>380        /// If the pipeline is terminated due to ActionPreference.Stop381        /// or ActionPreference.Inquire, this method will throw382        /// <see cref="System.Management.Automation.PipelineStoppedException"/>,383        /// but the command failure will ultimately be384        /// <see cref="System.Management.Automation.ActionPreferenceStopException"/>,385        /// </remarks>386        public void WriteProgress(387            Int64 sourceId,388            ProgressRecord progressRecord)389        {390            WriteProgress(sourceId, progressRecord, false);391        }392 393        internal bool IsWriteProgressEnabled()394            => WriteHelper_ShouldWrite(ProgressPreference, lastProgressContinueStatus);395 396        internal void WriteProgress(397                Int64 sourceId,398                ProgressRecord progressRecord,399                bool overrideInquire)400        {401            if (progressRecord == null)402            {403                throw PSTraceSource.NewArgumentNullException(nameof(progressRecord));404            }405 406            if (Host == null || Host.UI == null)407            {408                Diagnostics.Assert(false, "No host in CommandBase.WriteProgress()");409                throw PSTraceSource.NewInvalidOperationException();410            }411 412            InternalHostUserInterface ui = Host.UI as InternalHostUserInterface;413 414            ActionPreference preference = ProgressPreference;415            if (overrideInquire && preference == ActionPreference.Inquire)416            {417                preference = ActionPreference.Continue;418            }419 420            if (WriteHelper_ShouldWrite(421                preference, lastProgressContinueStatus))422            {423                // Break into the debugger if requested424                if (preference == ActionPreference.Break)425                {426                    CBhost?.Runspace?.Debugger?.Break(progressRecord);427                }428 429                ui.WriteProgress(sourceId, progressRecord);430            }431 432            lastProgressContinueStatus = WriteHelper(433                null,434                null,435                preference,436                lastProgressContinueStatus,437                "ProgressPreference",438                progressRecord.Activity);439        }440 441        /// <summary>442        /// Display debug information.443        /// </summary>444        /// <param name="text">Debug output.</param>445        /// <exception cref="System.Management.Automation.PipelineStoppedException">446        /// The pipeline has already been terminated, or was terminated447        /// during the execution of this method.448        /// The Cmdlet should generally just allow PipelineStoppedException449        /// to percolate up to the caller of ProcessRecord etc.450        /// </exception>451        /// <exception cref="System.InvalidOperationException">452        /// Not permitted at this time or from this thread.453        /// WriteDebug may only be called during a call to this Cmdlet's454        /// implementation of ProcessRecord, BeginProcessing or EndProcessing,455        /// and only from that thread.456        /// </exception>457        /// <remarks>458        /// Use WriteDebug to display debug information on the inner workings459        /// of your Cmdlet.  By default, debug output will460        /// not be displayed, although this can be configured with the461        /// DebugPreference shell variable or the -Debug command-line option.462        /// </remarks>463        /// <remarks>464        /// If the pipeline is terminated due to ActionPreference.Stop465        /// or ActionPreference.Inquire, this method will throw466        /// <see cref="System.Management.Automation.PipelineStoppedException"/>,467        /// but the command failure will ultimately be468        /// <see cref="System.Management.Automation.ActionPreferenceStopException"/>,469        /// </remarks>470        /// <seealso cref="System.Management.Automation.Cmdlet.WriteVerbose(string)"/>471        /// <seealso cref="System.Management.Automation.Cmdlet.WriteWarning(string)"/>472        /// <seealso cref="System.Management.Automation.Cmdlet.WriteProgress(ProgressRecord)"/>473        public void WriteDebug(string text)474        {475            WriteDebug(new DebugRecord(text));476        }477 478        internal bool IsWriteDebugEnabled()479            => WriteHelper_ShouldWrite(DebugPreference, lastDebugContinueStatus);480 481        /// <summary>482        /// Display debug information.483        /// </summary>484        internal void WriteDebug(DebugRecord record, bool overrideInquire = false)485        {486            ActionPreference preference = DebugPreference;487            if (overrideInquire && preference == ActionPreference.Inquire)488                preference = ActionPreference.Continue;489 490            if (WriteHelper_ShouldWrite(preference, lastDebugContinueStatus))491            {492                if (record.InvocationInfo == null)493                {494                    record.SetInvocationInfo(MyInvocation);495                }496 497                // Break into the debugger if requested498                if (preference == ActionPreference.Break)499                {500                    CBhost?.Runspace?.Debugger?.Break(record);501                }502 503                if (DebugOutputPipe != null)504                {505                    if (CBhost != null && CBhost.InternalUI != null &&506                        DebugOutputPipe.NullPipe)507                    {508                        // If redirecting to a null pipe, still write to509                        // information buffers.510                        CBhost.InternalUI.WriteDebugInfoBuffers(record);511                    }512 513                    // Set WriteStream so that the debug output is formatted correctly.514                    PSObject debugWrap = PSObject.AsPSObject(record);515                    debugWrap.WriteStream = WriteStreamType.Debug;516 517                    DebugOutputPipe.Add(debugWrap);518                }519                else520                {521                    //522                    // If no pipe, write directly to host.523                    //524                    if (Host == null || Host.UI == null)525                    {526                        Diagnostics.Assert(false, "No host in CommandBase.WriteDebug()");527                        throw PSTraceSource.NewInvalidOperationException();528                    }529 530                    CBhost.InternalUI.TranscribeResult(StringUtil.Format(InternalHostUserInterfaceStrings.DebugFormatString, record.Message));531                    CBhost.InternalUI.WriteDebugRecord(record);532                }533            }534 535            lastDebugContinueStatus = WriteHelper(536                null,537                null,538                preference,539                lastDebugContinueStatus,540                "DebugPreference",541                record.Message);542        }543 544        /// <summary>545        /// Display verbose information.546        /// </summary>547        /// <param name="text">Verbose output.</param>548        /// <exception cref="System.Management.Automation.PipelineStoppedException">549        /// The pipeline has already been terminated, or was terminated550        /// during the execution of this method.551        /// The Cmdlet should generally just allow PipelineStoppedException552        /// to percolate up to the caller of ProcessRecord etc.553        /// </exception>554        /// <exception cref="System.InvalidOperationException">555        /// Not permitted at this time or from this thread.556        /// WriteVerbose may only be called during a call to this Cmdlet's557        /// implementation of ProcessRecord, BeginProcessing or EndProcessing,558        /// and only from that thread.559        /// </exception>560        /// <remarks>561        /// Use WriteVerbose to display more detailed information about562        /// the activity of your Cmdlet.  By default, verbose output will563        /// not be displayed, although this can be configured with the564        /// VerbosePreference shell variable565        /// or the -Verbose and -Debug command-line options.566        /// </remarks>567        /// <seealso cref="System.Management.Automation.Cmdlet.WriteDebug(string)"/>568        /// <seealso cref="System.Management.Automation.Cmdlet.WriteWarning(string)"/>569        /// <seealso cref="System.Management.Automation.Cmdlet.WriteProgress(ProgressRecord)"/>570        public void WriteVerbose(string text)571        {572            WriteVerbose(new VerboseRecord(text));573        }574 575        internal bool IsWriteVerboseEnabled()576            => WriteHelper_ShouldWrite(VerbosePreference, lastVerboseContinueStatus);577 578        /// <summary>579        /// Display verbose information.580        /// </summary>581        internal void WriteVerbose(VerboseRecord record, bool overrideInquire = false)582        {583            ActionPreference preference = VerbosePreference;584            if (overrideInquire && preference == ActionPreference.Inquire)585                preference = ActionPreference.Continue;586 587            if (WriteHelper_ShouldWrite(preference, lastVerboseContinueStatus))588            {589                if (record.InvocationInfo == null)590                {591                    record.SetInvocationInfo(MyInvocation);592                }593 594                // Break into the debugger if requested595                if (preference == ActionPreference.Break)596                {597                    CBhost?.Runspace?.Debugger?.Break(record);598                }599 600                if (VerboseOutputPipe != null)601                {602                    if (CBhost != null && CBhost.InternalUI != null &&603                        VerboseOutputPipe.NullPipe)604                    {605                        // If redirecting to a null pipe, still write to606                        // information buffers.607                        CBhost.InternalUI.WriteVerboseInfoBuffers(record);608                    }609 610                    // Add WriteStream so that the verbose output is formatted correctly.611                    PSObject verboseWrap = PSObject.AsPSObject(record);612                    verboseWrap.WriteStream = WriteStreamType.Verbose;613 614                    VerboseOutputPipe.Add(verboseWrap);615                }616                else617                {618                    //619                    // If no pipe, write directly to host.620                    //621                    if (Host == null || Host.UI == null)622                    {623                        Diagnostics.Assert(false, "No host in CommandBase.WriteVerbose()");624                        throw PSTraceSource.NewInvalidOperationException();625                    }626 627                    CBhost.InternalUI.TranscribeResult(StringUtil.Format(InternalHostUserInterfaceStrings.VerboseFormatString, record.Message));628                    CBhost.InternalUI.WriteVerboseRecord(record);629                }630            }631 632            lastVerboseContinueStatus = WriteHelper(633                null,634                null,635                preference,636                lastVerboseContinueStatus,637                "VerbosePreference",638                record.Message);639        }640 641        /// <summary>642        /// Display warning information.643        /// </summary>644        /// <param name="text">Warning output.</param>645        /// <exception cref="System.Management.Automation.PipelineStoppedException">646        /// The pipeline has already been terminated, or was terminated647        /// during the execution of this method.648        /// The Cmdlet should generally just allow PipelineStoppedException649        /// to percolate up to the caller of ProcessRecord etc.650        /// </exception>651        /// <exception cref="System.InvalidOperationException">652        /// Not permitted at this time or from this thread.653        /// WriteWarning may only be called during a call to this Cmdlet's654        /// implementation of ProcessRecord, BeginProcessing or EndProcessing,655        /// and only from that thread.656        /// </exception>657        /// <remarks>658        /// Use WriteWarning to display warnings about659        /// the activity of your Cmdlet.  By default, warning output will660        /// be displayed, although this can be configured with the661        /// WarningPreference shell variable662        /// or the -Verbose and -Debug command-line options.663        /// </remarks>664        /// <seealso cref="System.Management.Automation.Cmdlet.WriteDebug(string)"/>665        /// <seealso cref="System.Management.Automation.Cmdlet.WriteVerbose(string)"/>666        /// <seealso cref="System.Management.Automation.Cmdlet.WriteProgress(ProgressRecord)"/>667        public void WriteWarning(string text)668        {669            WriteWarning(new WarningRecord(text));670        }671 672        internal bool IsWriteWarningEnabled()673            => WriteHelper_ShouldWrite(WarningPreference, lastWarningContinueStatus);674 675        /// <summary>676        /// Display warning information.677        /// </summary>678        internal void WriteWarning(WarningRecord record, bool overrideInquire = false)679        {680            ActionPreference preference = WarningPreference;681            if (overrideInquire && preference == ActionPreference.Inquire)682                preference = ActionPreference.Continue;683 684            if (WriteHelper_ShouldWrite(preference, lastWarningContinueStatus))685            {686                if (record.InvocationInfo == null)687                {688                    record.SetInvocationInfo(MyInvocation);689                }690 691                // Break into the debugger if requested692                if (preference == ActionPreference.Break)693                {694                    CBhost?.Runspace?.Debugger?.Break(record);695                }696 697                if (WarningOutputPipe != null)698                {699                    if (CBhost != null && CBhost.InternalUI != null &&700                        WarningOutputPipe.NullPipe)701                    {702                        // If redirecting to a null pipe, still write to703                        // information buffers.704                        CBhost.InternalUI.WriteWarningInfoBuffers(record);705                    }706 707                    // Add WriteStream so that the warning output is formatted correctly.708                    PSObject warningWrap = PSObject.AsPSObject(record);709                    warningWrap.WriteStream = WriteStreamType.Warning;710 711                    WarningOutputPipe.AddWithoutAppendingOutVarList(warningWrap);712                }713                else714                {715                    //716                    // If no pipe, write directly to host.717                    //718                    if (Host == null || Host.UI == null)719                    {720                        Diagnostics.Assert(false, "No host in CommandBase.WriteWarning()");721                        throw PSTraceSource.NewInvalidOperationException();722                    }723 724                    CBhost.InternalUI.TranscribeResult(StringUtil.Format(InternalHostUserInterfaceStrings.WarningFormatString, record.Message));725                    CBhost.InternalUI.WriteWarningRecord(record);726                }727            }728 729            AppendWarningVarList(record);730 731            lastWarningContinueStatus = WriteHelper(732                null,733                null,734                preference,735                lastWarningContinueStatus,736                "WarningPreference",737                record.Message);738        }739 740        /// <summary>741        /// Display tagged object information.742        /// </summary>743        public void WriteInformation(InformationRecord informationRecord)744        {745            WriteInformation(informationRecord, false);746        }747 748        internal bool IsWriteInformationEnabled()749            => WriteHelper_ShouldWrite(InformationPreference, lastInformationContinueStatus);750 751        /// <summary>752        /// Display tagged object information.753        /// </summary>754        internal void WriteInformation(InformationRecord record, bool overrideInquire = false)755        {756            ActionPreference preference = InformationPreference;757            if (overrideInquire && preference == ActionPreference.Inquire)758                preference = ActionPreference.Continue;759 760            // Break into the debugger if requested761            if (preference == ActionPreference.Break)762            {763                CBhost?.Runspace?.Debugger?.Break(record);764            }765 766            if (preference != ActionPreference.Ignore)767            {768                if (InformationOutputPipe != null)769                {770                    if (CBhost != null && CBhost.InternalUI != null &&771                        InformationOutputPipe.NullPipe)772                    {773                        // If redirecting to a null pipe, still write to774                        // information buffers.775                        CBhost.InternalUI.WriteInformationInfoBuffers(record);776                    }777 778                    // Add WriteStream so that the information output is formatted correctly.779                    PSObject informationWrap = PSObject.AsPSObject(record);780                    informationWrap.WriteStream = WriteStreamType.Information;781 782                    InformationOutputPipe.Add(informationWrap);783                }784                else785                {786                    //787                    // If no pipe, write directly to host.788                    //789                    if (Host == null || Host.UI == null)790                    {791                        throw PSTraceSource.NewInvalidOperationException("No host in CommandBase.WriteInformation()");792                    }793 794                    CBhost.InternalUI.WriteInformationRecord(record);795 796                    if ((record.Tags.Contains("PSHOST") && (!record.Tags.Contains("FORWARDED")))797                        || (preference == ActionPreference.Continue))798                    {799                        HostInformationMessage hostOutput = record.MessageData as HostInformationMessage;800                        if (hostOutput != null)801                        {802                            string message = hostOutput.Message;803                            ConsoleColor? foregroundColor = null;804                            ConsoleColor? backgroundColor = null;805                            bool noNewLine = false;806 807                            if (hostOutput.ForegroundColor.HasValue)808                            {809                                foregroundColor = hostOutput.ForegroundColor.Value;810                            }811 812                            if (hostOutput.BackgroundColor.HasValue)813                            {814                                backgroundColor = hostOutput.BackgroundColor.Value;815                            }816 817                            if (hostOutput.NoNewLine.HasValue)818                            {819                                noNewLine = hostOutput.NoNewLine.Value;820                            }821 822                            if (foregroundColor.HasValue || backgroundColor.HasValue)823                            {824                                // It is possible for either one or the other to be empty if run from a825                                // non-interactive host, but only one was specified in Write-Host.826                                // So fill them with defaults if they are empty.827                                if (!foregroundColor.HasValue)828                                {829                                    foregroundColor = ConsoleColor.Gray;830                                }831 832                                if (!backgroundColor.HasValue)833                                {834                                    backgroundColor = ConsoleColor.Black;835                                }836 837                                if (noNewLine)838                                {839                                    CBhost.InternalUI.Write(foregroundColor.Value, backgroundColor.Value, message);840                                }841                                else842                                {843                                    CBhost.InternalUI.WriteLine(foregroundColor.Value, backgroundColor.Value, message);844                                }845                            }846                            else847                            {848                                if (noNewLine)849                                {850                                    CBhost.InternalUI.Write(message);851                                }852                                else853                                {854                                    CBhost.InternalUI.WriteLine(message);855                                }856                            }857                        }858                        else859                        {860                            CBhost.InternalUI.WriteLine(record.ToString());861                        }862                    }863                }864 865                // Both informational and PSHost-targeted messages are transcribed here.866                // The only difference between these two is that PSHost-targeted messages are transcribed867                // even if InformationAction is SilentlyContinue.868                if (record.Tags.Contains("PSHOST") || (preference != ActionPreference.SilentlyContinue))869                {870                    CBhost.InternalUI.TranscribeResult(record.ToString());871                }872            }873 874            AppendInformationVarList(record);875 876            lastInformationContinueStatus = WriteHelper(877                null,878                null,879                preference,880                lastInformationContinueStatus,881                "InformationPreference",882                record.ToString());883        }884 885        /// <summary>886        /// Write text into pipeline execution log.887        /// </summary>888        /// <param name="text">Text to be written to log.</param>889        /// <remarks>890        /// Use WriteCommandDetail to write important information about cmdlet execution to891        /// pipeline execution log.892        ///893        /// If LogPipelineExecutionDetail is turned on, this information will be written894        /// to PowerShell log under log category "Pipeline execution detail"895        /// </remarks>896        /// <seealso cref="System.Management.Automation.ICommandRuntime.WriteDebug(string)"/>897        /// <seealso cref="System.Management.Automation.ICommandRuntime.WriteVerbose(string)"/>898        /// <seealso cref="System.Management.Automation.ICommandRuntime.WriteProgress(ProgressRecord)"/>899        public void WriteCommandDetail(string text)900        {901            this.PipelineProcessor.LogExecutionInfo(_thisCommand.MyInvocation, text);902        }903 904        internal bool LogPipelineExecutionDetail { get; } = false;905 906        private bool InitShouldLogPipelineExecutionDetail()907        {908            CmdletInfo cmdletInfo = _commandInfo as CmdletInfo;909 910            if (cmdletInfo != null)911            {912                if (string.Equals("Add-Type", cmdletInfo.Name, StringComparison.OrdinalIgnoreCase))913                {914                    return true;915                }916 917                if (cmdletInfo.Module == null && cmdletInfo.PSSnapIn != null)918                {919                    return cmdletInfo.PSSnapIn.LogPipelineExecutionDetails;920                }921 922                if (cmdletInfo.PSSnapIn == null && cmdletInfo.Module != null)923                {924                    return cmdletInfo.Module.LogPipelineExecutionDetails;925                }926 927                return false;928            }929 930            // Logging should be enabled for functions from modules also931            FunctionInfo functionInfo = _commandInfo as FunctionInfo;932            if (functionInfo != null && functionInfo.Module != null)933            {934                return functionInfo.Module.LogPipelineExecutionDetails;935            }936 937            return false;938        }939 940        /// <summary>941        /// This allows all success output to be set to a variable, where the variable is reset for each item returned by942        /// the cmdlet. Semantically this is equivalent to :  cmd | % { $pipelineVariable = $_; (...) }943        /// </summary>944        internal string PipelineVariable { get; set; }945 946        private PSVariable _pipelineVarReference;947        private bool _shouldRemovePipelineVariable;948 949        internal void SetupOutVariable()950        {951            if (string.IsNullOrEmpty(this.OutVariable))952            {953                return;954            }955 956            EnsureVariableParameterAllowed();957 958            // Handle the creation of OutVariable in the case of Out-Default specially,959            // as it needs to handle much of its OutVariable support itself.960            if (!OutVariable.StartsWith('+') &&961                string.Equals("Out-Default", _commandInfo.Name, StringComparison.OrdinalIgnoreCase))962            {963                _state ??= new SessionState(Context.EngineSessionState);964 965                IList oldValue = null;966                oldValue = PSObject.Base(_state.PSVariable.GetValue(this.OutVariable)) as IList;967 968                _outVarList = oldValue ?? new ArrayList();969 970                if (_thisCommand is not PSScriptCmdlet)971                {972                    this.OutputPipe.AddVariableList(VariableStreamKind.Output, _outVarList);973                }974 975                _state.PSVariable.Set(this.OutVariable, _outVarList);976            }977            else978            {979                SetupVariable(VariableStreamKind.Output, this.OutVariable, ref _outVarList);980            }981        }982 983        internal void SetupPipelineVariable()984        {985            // This can't use the common SetupVariable implementation, as this needs to persist for an entire986            // pipeline.987 988            if (string.IsNullOrEmpty(PipelineVariable))989            {990                return;991            }992 993            EnsureVariableParameterAllowed();994 995            _state ??= new SessionState(Context.EngineSessionState);996 997            // Create the pipeline variable998            _pipelineVarReference = new PSVariable(PipelineVariable);999            object varToUse = _state.Internal.SetVariable(1000                _pipelineVarReference,1001                force: false,1002                CommandOrigin.Internal);1003 1004            if (ReferenceEquals(_pipelineVarReference, varToUse))1005            {1006                // The returned variable is the exact same instance, which means we set a new variable.1007                // In this case, we will try removing the pipeline variable in the end.1008                _shouldRemovePipelineVariable = true;1009            }1010            else1011            {1012                // A variable with the same name already exists in the same scope and it was returned.1013                // In this case, we update the reference and don't remove the variable in the end.1014                _pipelineVarReference = (PSVariable)varToUse;1015            }1016 1017            if (_thisCommand is not PSScriptCmdlet)1018            {1019                this.OutputPipe.SetPipelineVariable(_pipelineVarReference);1020            }1021        }1022 1023        internal void RemovePipelineVariable()1024        {1025            if (_shouldRemovePipelineVariable)1026            {1027                // Remove pipeline variable when a pipeline is being torn down.1028                _state.PSVariable.Remove(PipelineVariable);1029            }1030        }1031 1032        /// <summary>1033        /// Configures the number of objects to buffer before calling the downstream Cmdlet.1034        /// </summary>1035        /// <remarks>1036        /// This is a common parameter via class CommonParameters.1037        /// </remarks>1038        internal int OutBuffer1039        {1040            get { return OutputPipe.OutBufferCount; }1041 1042            set { OutputPipe.OutBufferCount = value; }1043        }1044 1045        #endregion Write1046 1047        #region Should1048        #region ShouldProcess1049        /// <summary>1050        /// Confirm the operation with the user.  Cmdlets which make changes1051        /// (e.g. delete files, stop services etc.) should call ShouldProcess1052        /// to give the user the opportunity to confirm that the operation1053        /// should actually be performed.1054        /// </summary>1055        /// <param name="target">1056        /// Name of the target resource being acted upon. This will1057        /// potentially be displayed to the user.1058        /// </param>1059        /// <exception cref="System.Management.Automation.PipelineStoppedException">1060        /// The pipeline has already been terminated, or was terminated1061        /// during the execution of this method.1062        /// The Cmdlet should generally just allow PipelineStoppedException1063        /// to percolate up to the caller of ProcessRecord etc.1064        /// </exception>1065        /// <exception cref="System.InvalidOperationException">1066        /// Not permitted at this time or from this thread.1067        /// ShouldProcess may only be called during a call to this Cmdlet's1068        /// implementation of ProcessRecord, BeginProcessing or EndProcessing,1069        /// and only from that thread.1070        /// </exception>1071        /// <returns>1072        /// If ShouldProcess returns true, the operation should be performed.1073        /// If ShouldProcess returns false, the operation should not be1074        /// performed, and the Cmdlet should move on to the next target resource.1075        /// </returns>1076        /// <remarks>1077        /// A Cmdlet should declare1078        /// [Cmdlet( SupportsShouldProcess = true )]1079        /// if-and-only-if it calls ShouldProcess before making changes.1080        ///1081        /// ShouldProcess may only be called during a call to this Cmdlet's1082        /// implementation of ProcessRecord, BeginProcessing or EndProcessing,1083        /// and only from that thread.1084        ///1085        /// ShouldProcess will take into account command-line settings1086        /// and preference variables in determining what it should return1087        /// and whether it should prompt the user.1088        /// </remarks>1089        /// <remarks>1090        /// If the pipeline is terminated due to ActionPreference.Stop1091        /// or ActionPreference.Inquire,1092        /// <see cref="System.Management.Automation.Cmdlet.ShouldProcess(string)"/>1093        /// will throw1094        /// <see cref="System.Management.Automation.PipelineStoppedException"/>,1095        /// but the command failure will ultimately be1096        /// <see cref="System.Management.Automation.ActionPreferenceStopException"/>,1097        /// </remarks>1098        /// <example>1099        ///     <code>1100        ///         namespace Microsoft.Samples.Cmdlet1101        ///         {1102        ///             [Cmdlet(VerbsCommon.Remove,"myobjecttype1")]1103        ///             public class RemoveMyObjectType1 : PSCmdlet1104        ///             {1105        ///                 [Parameter( Mandatory = true )]1106        ///                 public string Filename1107        ///                 {1108        ///                     get { return filename; }1109        ///                     set { filename = value; }1110        ///                 }1111        ///                 private string filename;1112        ///1113        ///                 public override void ProcessRecord()1114        ///                 {1115        ///                     if (ShouldProcess(filename))1116        ///                     {1117        ///                         // delete the object1118        ///                     }1119        ///                 }1120        ///             }1121        ///         }1122        ///     </code>1123        /// </example>1124        /// <seealso cref="System.Management.Automation.Cmdlet.ShouldProcess(string,string)"/>1125        /// <seealso cref="System.Management.Automation.Cmdlet.ShouldProcess(string,string,string)"/>1126        /// <seealso cref="System.Management.Automation.Cmdlet.ShouldProcess(string,string,string,out ShouldProcessReason)"/>1127        /// <seealso cref="System.Management.Automation.Cmdlet.ShouldContinue(string,string)"/>1128        /// <seealso cref="System.Management.Automation.Cmdlet.ShouldContinue(string,string,ref bool,ref bool)"/>1129        public bool ShouldProcess(string target)1130        {1131            string verboseDescription = StringUtil.Format(CommandBaseStrings.ShouldProcessMessage,1132                MyInvocation.MyCommand.Name,1133                target);1134            ShouldProcessReason shouldProcessReason;1135            return DoShouldProcess(verboseDescription, null, null, out shouldProcessReason);1136        }1137 1138        /// <summary>1139        /// Confirm the operation with the user.  Cmdlets which make changes1140        /// (e.g. delete files, stop services etc.) should call ShouldProcess1141        /// to give the user the opportunity to confirm that the operation1142        /// should actually be performed.1143        ///1144        /// This variant allows the caller to specify text for both the1145        /// target resource and the action.1146        /// </summary>1147        /// <param name="target">1148        /// Name of the target resource being acted upon. This will1149        /// potentially be displayed to the user.1150        /// </param>1151        /// <param name="action">1152        /// Name of the action which is being performed. This will1153        /// potentially be displayed to the user. (default is Cmdlet name)1154        /// </param>1155        /// <exception cref="System.Management.Automation.PipelineStoppedException">1156        /// The pipeline has already been terminated, or was terminated1157        /// during the execution of this method.1158        /// The Cmdlet should generally just allow PipelineStoppedException1159        /// to percolate up to the caller of ProcessRecord etc.1160        /// </exception>1161        /// <exception cref="System.InvalidOperationException">1162        /// Not permitted at this time or from this thread.1163        /// ShouldProcess may only be called during a call to this Cmdlet's1164        /// implementation of ProcessRecord, BeginProcessing or EndProcessing,1165        /// and only from that thread.1166        /// </exception>1167        /// <returns>1168        /// If ShouldProcess returns true, the operation should be performed.1169        /// If ShouldProcess returns false, the operation should not be1170        /// performed, and the Cmdlet should move on to the next target resource.1171        /// </returns>1172        /// <remarks>1173        /// A Cmdlet should declare1174        /// [Cmdlet( SupportsShouldProcess = true )]1175        /// if-and-only-if it calls ShouldProcess before making changes.1176        ///1177        /// ShouldProcess may only be called during a call to this Cmdlet's1178        /// implementation of ProcessRecord, BeginProcessing or EndProcessing,1179        /// and only from that thread.1180        ///1181        /// ShouldProcess will take into account command-line settings1182        /// and preference variables in determining what it should return1183        /// and whether it should prompt the user.1184        /// </remarks>1185        /// <remarks>1186        /// If the pipeline is terminated due to ActionPreference.Stop1187        /// or ActionPreference.Inquire, this method will throw1188        /// <see cref="System.Management.Automation.PipelineStoppedException"/>,1189        /// but the command failure will ultimately be1190        /// <see cref="System.Management.Automation.ActionPreferenceStopException"/>,1191        /// </remarks>1192        /// <example>1193        ///     <code>1194        ///         namespace Microsoft.Samples.Cmdlet1195        ///         {1196        ///             [Cmdlet(VerbsCommon.Remove,"myobjecttype2")]1197        ///             public class RemoveMyObjectType2 : PSCmdlet1198        ///             {1199        ///                 [Parameter( Mandatory = true )]1200        ///                 public string Filename

Showing the first 1,200 of 3830 lines. Download the file for the rest.