Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
Job.cs4525 linesDownload Raw Back to client
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System.Collections.Generic;5using System.Collections.ObjectModel;6using System.Diagnostics.CodeAnalysis;7using System.Management.Automation.Host;8using System.Management.Automation.Internal;9using System.Management.Automation.Language;10using System.Management.Automation.Remoting;11using System.Management.Automation.Remoting.Internal;12using System.Management.Automation.Runspaces;13using System.Management.Automation.Tracing;14using System.Runtime.Serialization;15using System.Text;16using System.Threading;17 18using Microsoft.PowerShell.Commands;19 20using Dbg = System.Management.Automation.Diagnostics;21 22// Stops compiler from warning about unknown warnings23#pragma warning disable 1634, 169124 25namespace System.Management.Automation26{27    /// <summary>28    /// Enumeration for job status values. Indicates the status29    /// of the result object.30    /// </summary>31    public enum JobState32    {33        /// <summary>34        /// Execution of command in job not started.35        /// </summary>36        NotStarted = 0,37 38        /// <summary>39        /// Execution of command in progress.40        /// </summary>41        Running = 1,42 43        /// <summary>44        /// Execution of command completed in all45        /// computernames/runspaces.46        /// </summary>47        Completed = 2,48 49        /// <summary>50        /// An error was encountered when trying to executed51        /// command in one or more computernames/runspaces.52        /// </summary>53        Failed = 3,54 55        /// <summary>56        /// Command execution is cancelled (stopped) in one or more57        /// computernames/runspaces.58        /// </summary>59        Stopped = 4,60 61        /// <summary>62        /// Command execution is blocked (on user input host calls etc)63        /// </summary>64        Blocked = 5,65 66        /// <summary>67        /// The job has been suspended.68        /// </summary>69        Suspended = 6,70 71        /// <summary>72        /// The job is a remote job and has been disconnected from the server.73        /// </summary>74        Disconnected = 7,75 76        /// <summary>77        /// Suspend is in progress.78        /// </summary>79        Suspending = 8,80 81        /// <summary>82        /// Stop is in progress.83        /// </summary>84        Stopping = 9,85 86        /// <summary>87        /// Script execution is halted in a debugger stop.88        /// </summary>89        AtBreakpoint = 1090    }91 92    /// <summary>93    /// Defines exception which is thrown when state of the PSJob is different94    /// from the expected state.95    /// </summary>96    public class InvalidJobStateException : SystemException97    {98        /// <summary>99        /// Creates a new instance of InvalidPSJobStateException class.100        /// </summary>101        public InvalidJobStateException()102            : base103        (104            PSRemotingErrorInvariants.FormatResourceString105            (106                RemotingErrorIdStrings.InvalidJobStateGeneral107            )108        )109        {110        }111 112        /// <summary>113        /// Creates a new instance of InvalidPSJobStateException class.114        /// </summary>115        /// <param name="message">116        /// The error message that explains the reason for the exception.117        /// </param>118        public InvalidJobStateException(string message)119            : base(message)120        {121        }122 123        /// <summary>124        /// Creates a new instance of InvalidPSJobStateException class.125        /// </summary>126        /// <param name="message">127        /// The error message that explains the reason for the exception.128        /// </param>129        /// <param name="innerException">130        /// The exception that is the cause of the current exception.131        /// </param>132        public InvalidJobStateException(string message, Exception innerException)133            : base(message, innerException)134        {135        }136 137        /// <summary>138        /// Creates a new instance of InvalidJobStateException class.139        /// </summary>140        /// <param name="currentState">141        /// The Job State at the time of the error.142        /// </param>143        /// <param name="actionMessage">144        /// An additional message that gives more information about the error. Used145        /// for context after a generalized error message.146        /// </param>147        public InvalidJobStateException(JobState currentState, string actionMessage)148            : base149        (150            PSRemotingErrorInvariants.FormatResourceString151            (152                RemotingErrorIdStrings.InvalidJobStateSpecific, currentState, actionMessage153            )154        )155        {156            _currState = currentState;157        }158 159        /// <summary>160        /// Initializes a new instance of the InvalidPSJobStateException and defines value of161        /// CurrentState.162        /// </summary>163        /// <param name="currentState">Current state of powershell.</param>164        internal InvalidJobStateException(JobState currentState)165            : base166        (167            PSRemotingErrorInvariants.FormatResourceString168            (169                RemotingErrorIdStrings.InvalidJobStateGeneral170            )171        )172        {173            _currState = currentState;174        }175 176        #region ISerializable Members177 178        // No need to implement GetObjectData179        // if all fields are static or [NonSerialized]180 181        /// <summary>182        /// Initializes a new instance of the InvalidPSJobStateException183        /// class with serialized data.184        /// </summary>185        /// <param name="info">186        /// The <see cref="SerializationInfo"/> that holds the serialized object187        /// data about the exception being thrown.188        /// </param>189        /// <param name="context">190        /// The <see cref="StreamingContext"/> that contains contextual information191        /// about the source or destination.192        /// </param>193        [Obsolete("Legacy serialization support is deprecated since .NET 8", DiagnosticId = "SYSLIB0051")] 194        protected195        InvalidJobStateException(SerializationInfo info, StreamingContext context)196        {197            throw new NotSupportedException();198        }199 200        #endregion201 202        /// <summary>203        /// Gets CurrentState of the Job.204        /// </summary>205        public JobState CurrentState206        {207            get208            {209                return _currState;210            }211        }212 213        /// <summary>214        /// State of job when exception was thrown.215        /// </summary>216        [NonSerialized]217        private readonly JobState _currState = 0;218    }219 220    /// <summary>221    /// Type which has information about JobState and Exception222    /// ,if any, associated with JobState.223    /// </summary>224    public sealed class JobStateInfo225    {226        #region constructors227 228        /// <summary>229        /// Constructor for state changes not resulting from an error.230        /// </summary>231        /// <param name="state">Execution state.</param>232        public JobStateInfo(JobState state)233            : this(state, null)234        {235        }236 237        /// <summary>238        /// Constructor for state changes with an optional error.239        /// </summary>240        /// <param name="state">The new state.</param>241        /// <param name="reason">A non-null exception if the state change was242        /// caused by an error,otherwise; null.243        /// </param>244        public JobStateInfo(JobState state, Exception reason)245        {246            State = state;247            Reason = reason;248        }249 250        /// <summary>251        /// Copy constructor to support cloning.252        /// </summary>253        /// <param name="jobStateInfo">Source information.</param>254        /// <throws>255        /// ArgumentNullException when <paramref name="jobStateInfo"/> is null.256        /// </throws>257        internal JobStateInfo(JobStateInfo jobStateInfo)258        {259            State = jobStateInfo.State;260            Reason = jobStateInfo.Reason;261        }262 263        #endregion constructors264 265        #region public_properties266 267        /// <summary>268        /// The state of the job.269        /// </summary>270        /// <remarks>271        /// This value indicates the state of the job .272        /// </remarks>273        public JobState State { get; }274 275        /// <summary>276        /// The reason for the state change, if caused by an error.277        /// </summary>278        /// <remarks>279        /// The value of this property is non-null if the state280        /// changed due to an error. Otherwise, the value of this281        /// property is null.282        /// </remarks>283        public Exception Reason { get; }284 285        #endregion public_properties286 287        /// <summary>288        /// Override for ToString()289        /// </summary>290        /// <returns></returns>291        public override string ToString()292        {293            return State.ToString();294        }295 296        /// <summary>297        /// Clones this object.298        /// </summary>299        /// <returns>Cloned object.</returns>300        internal JobStateInfo Clone()301        {302            return new JobStateInfo(this);303        }304 305        #region private_fields306 307        #endregion private_fields308    }309 310    /// <summary>311    /// Event arguments passed to JobStateEvent handlers312    /// <see cref="Job.StateChanged"/> event.313    /// </summary>314    public sealed class JobStateEventArgs : EventArgs315    {316        #region constructors317 318        /// <summary>319        /// Constructor of JobStateEventArgs.320        /// </summary>321        /// <param name="jobStateInfo">The current state of the job.</param>322        public JobStateEventArgs(JobStateInfo jobStateInfo)323            : this(jobStateInfo, null)324        {325        }326 327        /// <summary>328        /// Constructor of JobStateEventArgs.329        /// </summary>330        /// <param name="jobStateInfo">The current state of the job.</param>331        /// <param name="previousJobStateInfo">The previous state of the job.</param>332        public JobStateEventArgs(JobStateInfo jobStateInfo, JobStateInfo previousJobStateInfo)333        {334            if (jobStateInfo == null)335            {336                throw PSTraceSource.NewArgumentNullException(nameof(jobStateInfo));337            }338 339            JobStateInfo = jobStateInfo;340            PreviousJobStateInfo = previousJobStateInfo;341        }342 343        #endregion constructors344 345        #region public_properties346 347        /// <summary>348        /// Info about the current state of the job.349        /// </summary>350        public JobStateInfo JobStateInfo { get; }351 352        /// <summary>353        /// Info about the previous state of the job.354        /// </summary>355        public JobStateInfo PreviousJobStateInfo { get; }356 357        #endregion public_properties358    }359 360    /// <summary>361    /// Object that must be created by PowerShell to allow reuse of an ID for a job.362    /// Also allows setting of the Instance Id so that jobs may be recreated.363    /// </summary>364    public sealed class JobIdentifier365    {366        internal JobIdentifier(int id, Guid instanceId)367        {368            if (id <= 0)369                PSTraceSource.NewArgumentException(nameof(id), RemotingErrorIdStrings.JobSessionIdLessThanOne, id);370            Id = id;371            InstanceId = instanceId;372        }373 374        internal int Id { get; }375 376        internal Guid InstanceId { get; private set; }377    }378 379    /// <summary>380    /// Interface to expose a job debugger.381    /// </summary>382#nullable enable383    public interface IJobDebugger384    {385        /// <summary>386        /// Job Debugger.387        /// </summary>388        Debugger? Debugger389        {390            get;391        }392 393        /// <summary>394        /// True if job is running asynchronously.395        /// </summary>396        bool IsAsync397        {398            get;399            set;400        }401    }402#nullable restore403 404    /// <summary>405    /// Represents a command running in background. A job object can internally406    /// contain many child job objects.407    /// </summary>408    public abstract class Job : IDisposable409    {410        #region Constructor411 412        /// <summary>413        /// Default constructor.414        /// </summary>415        protected Job()416        {417            Id = System.Threading.Interlocked.Increment(ref s_jobIdSeed);418        }419 420        /// <summary>421        /// Creates an instance of this class.422        /// </summary>423        /// <param name="command">Command invoked by this job object.</param>424        protected Job(string command)425            : this()426        {427            Command = command;428            _name = AutoGenerateJobName();429        }430 431        /// <summary>432        /// Creates an instance of this class.433        /// </summary>434        /// <param name="command">Command invoked by this job object.</param>435        /// <param name="name">Friendly name for the job object.</param>436        protected Job(string command, string name)437            : this(command)438        {439            if (!string.IsNullOrEmpty(name))440            {441                _name = name;442            }443        }444 445        /// <summary>446        /// Creates an instance of this class.447        /// </summary>448        /// <param name="command">Command invoked by this job object.</param>449        /// <param name="name">Friendly name for the job object.</param>450        /// <param name="childJobs">Child jobs of this job object.</param>451        protected Job(string command, string name, IList<Job> childJobs)452            : this(command, name)453        {454            _childJobs = childJobs;455        }456 457        /// <summary>458        /// Creates an instance of this class.459        /// </summary>460        /// <param name="command">Command invoked by this job object.</param>461        /// <param name="name">Friendly name for the job object.</param>462        /// <param name="token">Id and InstanceId pair to be used for this job object.</param>463        /// <remarks>The JobIdentifier is a token that must be issued by PowerShell to allow464        /// reuse of the Id. This is the only way to set either Id or instance Id.</remarks>465        protected Job(string command, string name, JobIdentifier token)466        {467            if (token == null)468                throw PSTraceSource.NewArgumentNullException(nameof(token), RemotingErrorIdStrings.JobIdentifierNull);469            if (token.Id > s_jobIdSeed)470            {471                throw PSTraceSource.NewArgumentException(nameof(token), RemotingErrorIdStrings.JobIdNotYetAssigned, token.Id);472            }473 474            Command = command;475 476            Id = token.Id;477            InstanceId = token.InstanceId;478 479            if (!string.IsNullOrEmpty(name))480            {481                _name = name;482            }483            else484            {485                _name = AutoGenerateJobName();486            }487        }488 489        /// <summary>490        /// Creates an instance of this class.491        /// </summary>492        /// <param name="command">Command invoked by this job object.</param>493        /// <param name="name">Friendly name for the job object.</param>494        /// <param name="instanceId">InstanceId to be used for this job object.</param>495        /// <remarks>The InstanceId may need to be set to maintain job identity across496        /// instances of the process.</remarks>497        protected Job(string command, string name, Guid instanceId)498            : this(command, name)499        {500            InstanceId = instanceId;501        }502 503        internal static string GetCommandTextFromInvocationInfo(InvocationInfo invocationInfo)504        {505            if (invocationInfo == null)506            {507                return null;508            }509 510            IScriptExtent scriptExtent = invocationInfo.ScriptPosition;511            if ((scriptExtent != null) && (scriptExtent.StartScriptPosition != null) && !string.IsNullOrWhiteSpace(scriptExtent.StartScriptPosition.Line))512            {513                Dbg.Assert(scriptExtent.StartScriptPosition.ColumnNumber > 0, "Column numbers start at 1");514                Dbg.Assert(scriptExtent.StartScriptPosition.ColumnNumber <= scriptExtent.StartScriptPosition.Line.Length, "Column numbers are not greater than the length of a line");515                return scriptExtent.StartScriptPosition.Line.AsSpan(scriptExtent.StartScriptPosition.ColumnNumber - 1).Trim().ToString();516            }517 518            return invocationInfo.InvocationName;519        }520 521        #endregion Constructor522 523        #region Private Members524 525        private ManualResetEvent _finished = new ManualResetEvent(false);526 527        private string _name;528        private IList<Job> _childJobs;529        internal readonly object syncObject = new object();   // object used for synchronization530        // ISSUE: Should Result be public property531        private PSDataCollection<PSStreamObject> _results = new PSDataCollection<PSStreamObject>();532        private bool _resultsOwner = true;533        private PSDataCollection<ErrorRecord> _error = new PSDataCollection<ErrorRecord>();534        private bool _errorOwner = true;535        private PSDataCollection<ProgressRecord> _progress = new PSDataCollection<ProgressRecord>();536        private bool _progressOwner = true;537        private PSDataCollection<VerboseRecord> _verbose = new PSDataCollection<VerboseRecord>();538        private bool _verboseOwner = true;539        private PSDataCollection<WarningRecord> _warning = new PSDataCollection<WarningRecord>();540        private bool _warningOwner = true;541        private PSDataCollection<DebugRecord> _debug = new PSDataCollection<DebugRecord>();542        private bool _debugOwner = true;543        private PSDataCollection<InformationRecord> _information = new PSDataCollection<InformationRecord>();544        private bool _informationOwner = true;545        private PSDataCollection<PSObject> _output = new PSDataCollection<PSObject>();546        private bool _outputOwner = true;547 548        /// <summary>549        /// Static variable which is incremented to generate id.550        /// </summary>551        private static int s_jobIdSeed = 0;552 553        private string _jobTypeName = string.Empty;554 555        #endregion Private Members556 557        #region Job Properties558 559        /// <summary>560        /// Command Invoked by this Job.561        /// </summary>562        public string Command { get; }563 564        /// <summary>565        /// Status of the command execution.566        /// </summary>567        public JobStateInfo JobStateInfo { get; private set; } = new JobStateInfo(JobState.NotStarted);568 569        /// <summary>570        /// Wait Handle which is signaled when job is finished.571        /// This is set when state of the job is set to Completed,572        /// Stopped or Failed.573        /// </summary>574        public WaitHandle Finished575        {576            get577            {578                lock (this.syncObject)579                {580                    if (_finished != null)581                    {582                        return _finished;583                    }584                    else585                    {586                        // Damage control mode:587                        // Somebody is trying to get Finished handle for an already disposed Job instance.588                        // Return an already triggered handle (disposed job is finished by definition).589                        // The newly created handle will not be disposed in a deterministic manner590                        // and in some circumstances can be mistaken for a handle leak.591                        return new ManualResetEvent(true);592                    }593                }594            }595        }596 597        /// <summary>598        /// Unique identifier for this job.599        /// </summary>600        public Guid InstanceId { get; } = Guid.NewGuid();601 602        /// <summary>603        /// Short identifier for this result which will be604        /// recycled and used within a process.605        /// </summary>606        public int Id { get; }607 608        /// <summary>609        /// Name for identifying this job object.610        /// </summary>611        public string Name612        {613            get614            {615                return _name;616            }617 618            set619            {620                AssertNotDisposed();621                _name = value;622            }623        }624 625        /// <summary>626        /// List of child jobs contained within this job.627        /// </summary>628        public IList<Job> ChildJobs629        {630            get631            {632                if (_childJobs == null)633                {634                    lock (syncObject)635                    {636                        _childJobs ??= new List<Job>();637                    }638                }639 640                return _childJobs;641            }642        }643 644        /// <summary>645        /// Success status of the command execution.646        /// </summary>647        public abstract string StatusMessage { get; }648 649        /// <summary>650        /// Indicates that more data is available in this651        /// result object for reading.652        /// </summary>653        public abstract bool HasMoreData { get; }654 655        /// <summary>656        /// Time job was started.657        /// </summary>658        public DateTime? PSBeginTime { get; protected set; } = null;659 660        /// <summary>661        /// Time job stopped.662        /// </summary>663        public DateTime? PSEndTime { get; protected set; } = null;664 665        /// <summary>666        /// Job type name.667        /// </summary>668        public string PSJobTypeName669        {670            get671            {672                return _jobTypeName;673            }674 675            protected internal set676            {677                _jobTypeName = value ?? this.GetType().ToString();678            }679        }680 681        #region results682 683        /// <summary>684        /// Result objects from this job. If this object is not a685        /// leaf node (with no children), then this will686        /// aggregate the results from all child jobs.687        /// </summary>688        internal PSDataCollection<PSStreamObject> Results689        {690            get691            {692                return _results;693            }694 695            set696            {697                if (value == null)698                {699                    throw PSTraceSource.NewArgumentNullException("Results");700                }701 702                lock (syncObject)703                {704                    AssertChangesAreAccepted();705                    _resultsOwner = false;706                    _results = value;707                }708            }709        }710 711        /// <summary>712        /// Indicates if a particular Job type uses the713        /// internal results collection.714        /// </summary>715        internal bool UsesResultsCollection { get; set; }716 717        /// <summary>718        /// Suppresses forwarding of job output into a cmdlet (like Receive-Job).719        /// This flag modifies functionality of <see cref="WriteObject"/> method, so that it doesnt add output-processing to <see cref="Results"/> collection.720        /// </summary>721        internal bool SuppressOutputForwarding { get; set; }722 723        internal virtual void WriteObject(object outputObject)724        {725            PSObject pso = (outputObject == null) ? null : PSObject.AsPSObject(outputObject);726            this.Output.Add(pso);727 728            if (!SuppressOutputForwarding)729            {730                this.Results.Add(new PSStreamObject(PSStreamObjectType.Output, pso));731            }732        }733 734        /// <summary>735        /// Allows propagating of terminating exceptions from remote "throw" statement736        /// (normally / by default all remote errors are transformed into non-terminating errors.737        /// </summary>738        internal bool PropagateThrows { get; set; }739 740        private void WriteError(Cmdlet cmdlet, ErrorRecord errorRecord)741        {742            if (this.PropagateThrows)743            {744                Exception e = GetExceptionFromErrorRecord(errorRecord);745                if (e != null)746                    throw e;747            }748 749            errorRecord.PreserveInvocationInfoOnce = true;750            cmdlet.WriteError(errorRecord);751        }752 753        private static Exception GetExceptionFromErrorRecord(ErrorRecord errorRecord)754        {755            if (errorRecord.Exception is not RuntimeException runtimeException)756                return null;757 758            if (runtimeException is not RemoteException remoteException)759                return null;760 761            PSPropertyInfo wasThrownFromThrow =762                remoteException.SerializedRemoteException.Properties["WasThrownFromThrowStatement"];763            if (wasThrownFromThrow == null || !((bool)wasThrownFromThrow.Value))764                return null;765 766            runtimeException.WasThrownFromThrowStatement = true;767            return runtimeException;768        }769 770        internal virtual void WriteError(ErrorRecord errorRecord)771        {772            Error.Add(errorRecord);773            if (PropagateThrows)774            {775                Exception exception = GetExceptionFromErrorRecord(errorRecord);776                if (exception != null)777                {778                    Results.Add(new PSStreamObject(PSStreamObjectType.Exception, exception));779                    return;780                }781            }782 783            Results.Add(new PSStreamObject(PSStreamObjectType.Error, errorRecord));784        }785 786        internal void WriteError(ErrorRecord errorRecord, out Exception exceptionThrownOnCmdletThread)787        {788            this.Error.Add(errorRecord);789            this.InvokeCmdletMethodAndWaitForResults<object>(790                (Cmdlet cmdlet) =>791                {792                    this.WriteError(cmdlet, errorRecord);793                    return null;794                },795                out exceptionThrownOnCmdletThread);796        }797 798        internal virtual void WriteWarning(string message)799        {800            this.Warning.Add(new WarningRecord(message));801            this.Results.Add(new PSStreamObject(PSStreamObjectType.Warning, message));802        }803 804        internal virtual void WriteVerbose(string message)805        {806            this.Verbose.Add(new VerboseRecord(message));807            this.Results.Add(new PSStreamObject(PSStreamObjectType.Verbose, message));808        }809 810        internal virtual void WriteDebug(string message)811        {812            this.Debug.Add(new DebugRecord(message));813            this.Results.Add(new PSStreamObject(PSStreamObjectType.Debug, message));814        }815 816        internal virtual void WriteProgress(ProgressRecord progressRecord)817        {818            if ((progressRecord.ParentActivityId == (-1)) && (_parentActivityId != null))819            {820                progressRecord = new ProgressRecord(progressRecord) { ParentActivityId = _parentActivityId.Value };821            }822 823            Progress.Add(progressRecord);824            Results.Add(new PSStreamObject(PSStreamObjectType.Progress, progressRecord));825        }826 827        internal virtual void WriteInformation(InformationRecord informationRecord)828        {829            Information.Add(informationRecord);830            Results.Add(new PSStreamObject(PSStreamObjectType.Information, informationRecord));831        }832 833        private Lazy<int> _parentActivityId;834 835        internal void SetParentActivityIdGetter(Func<int> parentActivityIdGetter)836        {837            Dbg.Assert(parentActivityIdGetter != null, "Caller should verify parentActivityIdGetter != null");838            _parentActivityId = new Lazy<int>(parentActivityIdGetter);839        }840 841        internal bool ShouldContinue(string query, string caption)842        {843            Exception exceptionThrownOnCmdletThread;844            return this.ShouldContinue(query, caption, out exceptionThrownOnCmdletThread);845        }846 847        internal bool ShouldContinue(string query, string caption, out Exception exceptionThrownOnCmdletThread)848        {849            bool methodResult = InvokeCmdletMethodAndWaitForResults(850                cmdlet => cmdlet.ShouldContinue(query, caption),851                out exceptionThrownOnCmdletThread);852            return methodResult;853        }854 855        internal virtual void NonblockingShouldProcess(856            string verboseDescription,857            string verboseWarning,858            string caption)859        {860            InvokeCmdletMethodAndIgnoreResults(861                (Cmdlet cmdlet) =>862                {863                    ShouldProcessReason throwAwayProcessReason;864                    cmdlet.ShouldProcess(865                        verboseDescription,866                        verboseWarning,867                        caption,868                        out throwAwayProcessReason);869                });870        }871 872        internal virtual bool ShouldProcess(873            string verboseDescription,874            string verboseWarning,875            string caption,876            out ShouldProcessReason shouldProcessReason,877            out Exception exceptionThrownOnCmdletThread)878        {879            ShouldProcessReason closureSafeShouldProcessReason = ShouldProcessReason.None;880 881            bool methodResult = InvokeCmdletMethodAndWaitForResults(882                cmdlet => cmdlet.ShouldProcess(883                    verboseDescription,884                    verboseWarning,885                    caption,886                    out closureSafeShouldProcessReason),887                out exceptionThrownOnCmdletThread);888 889            shouldProcessReason = closureSafeShouldProcessReason;890            return methodResult;891        }892 893        private void InvokeCmdletMethodAndIgnoreResults(Action<Cmdlet> invokeCmdletMethod)894        {895            object resultsLock = new object();896            CmdletMethodInvoker<object> methodInvoker = new CmdletMethodInvoker<object>897            {898                Action = (Cmdlet cmdlet) => { invokeCmdletMethod(cmdlet); return null; },899                Finished = null,900                SyncObject = resultsLock901            };902            Results.Add(new PSStreamObject(PSStreamObjectType.BlockingError, methodInvoker));903        }904 905        private T InvokeCmdletMethodAndWaitForResults<T>(Func<Cmdlet, T> invokeCmdletMethodAndReturnResult, out Exception exceptionThrownOnCmdletThread)906        {907            Dbg.Assert(invokeCmdletMethodAndReturnResult != null, "Caller should verify invokeCmdletMethodAndReturnResult != null");908 909            T methodResult = default(T);910            Exception closureSafeExceptionThrownOnCmdletThread = null;911            object resultsLock = new object();912            using (var gotResultEvent = new ManualResetEventSlim(false))913            {914                EventHandler<JobStateEventArgs> stateChangedEventHandler =915                    (object sender, JobStateEventArgs eventArgs) =>916                    {917                        if (IsFinishedState(eventArgs.JobStateInfo.State) || eventArgs.JobStateInfo.State == JobState.Stopping)918                        {919                            lock (resultsLock)920                            {921                                closureSafeExceptionThrownOnCmdletThread = new OperationCanceledException();922                            }923 924                            gotResultEvent.Set();925                        }926                    };927                this.StateChanged += stateChangedEventHandler;928                Interlocked.MemoryBarrier();929                try930                {931                    stateChangedEventHandler(null, new JobStateEventArgs(this.JobStateInfo));932 933                    if (!gotResultEvent.IsSet)934                    {935                        this.SetJobState(JobState.Blocked);936 937                        // addition to results column happens here938                        CmdletMethodInvoker<T> methodInvoker = new CmdletMethodInvoker<T>939                        {940                            Action = invokeCmdletMethodAndReturnResult,941                            Finished = gotResultEvent,942                            SyncObject = resultsLock943                        };944                        PSStreamObjectType objectType = PSStreamObjectType.ShouldMethod;945 946                        if (typeof(T) == typeof(object))947                            objectType = PSStreamObjectType.BlockingError;948 949                        Results.Add(new PSStreamObject(objectType, methodInvoker));950 951                        gotResultEvent.Wait();952                        this.SetJobState(JobState.Running);953 954                        lock (resultsLock)955                        {956                            if (closureSafeExceptionThrownOnCmdletThread == null) // stateChangedEventHandler didn't set the results?  = ok to clobber results?957                            {958                                closureSafeExceptionThrownOnCmdletThread = methodInvoker.ExceptionThrownOnCmdletThread;959                                methodResult = methodInvoker.MethodResult;960                            }961                        }962                    }963                }964                finally965                {966                    this.StateChanged -= stateChangedEventHandler;967                }968            }969 970            lock (resultsLock)971            {972                exceptionThrownOnCmdletThread = closureSafeExceptionThrownOnCmdletThread;973                return methodResult;974            }975        }976 977        internal virtual void ForwardAvailableResultsToCmdlet(Cmdlet cmdlet)978        {979            foreach (PSStreamObject obj in Results.ReadAll())980            {981                obj.WriteStreamObject(cmdlet);982            }983        }984 985        internal virtual void ForwardAllResultsToCmdlet(Cmdlet cmdlet)986        {987            foreach (PSStreamObject obj in this.Results)988            {989                obj.WriteStreamObject(cmdlet);990            }991        }992 993        /// <summary>994        /// This method is introduce for delaying the loading of streams995        /// for a particular job.996        /// </summary>997        protected virtual void DoLoadJobStreams()998        {999        }1000 1001        /// <summary>1002        /// Unloads job streams information. Enables jobs to1003        /// clear stream information from memory.1004        /// </summary>1005        protected virtual void DoUnloadJobStreams()1006        {1007        }1008 1009        /// <summary>1010        /// Load the required job streams.1011        /// </summary>1012        public void LoadJobStreams()1013        {1014            if (_jobStreamsLoaded)1015            {1016                return;1017            }1018 1019            lock (syncObject)1020            {1021                if (_jobStreamsLoaded)1022                {1023                    return;1024                }1025 1026                _jobStreamsLoaded = true;1027            }1028 1029            try1030            {1031                DoLoadJobStreams();1032            }1033            catch (Exception e)1034            {1035                // third party call-out for platform API1036                // Therefore it is fine to eat the exception1037                // here1038                using (PowerShellTraceSource tracer = PowerShellTraceSourceFactory.GetTraceSource())1039                {1040                    tracer.TraceException(e);1041                }1042            }1043        }1044 1045        private bool _jobStreamsLoaded;1046 1047        /// <summary>1048        /// Unload the required job streams.1049        /// </summary>1050        public void UnloadJobStreams()1051        {1052            if (!_jobStreamsLoaded) return;1053 1054            lock (syncObject)1055            {1056                if (!_jobStreamsLoaded) return;1057                _jobStreamsLoaded = false;1058            }1059 1060            try1061            {1062                DoUnloadJobStreams();1063            }1064            catch (Exception e)1065            {1066                // third party call-out for platform API1067                // Therefore it is fine to eat the exception1068                // here1069                using (PowerShellTraceSource tracer = PowerShellTraceSourceFactory.GetTraceSource())1070                {1071                    tracer.TraceException(e);1072                }1073            }1074        }1075 1076        /// <summary>1077        /// Gets or sets the output buffer. Output of job is written1078        /// into this buffer.1079        /// </summary>1080        /// <exception cref="ArgumentNullException">1081        /// Cannot set to a null value.1082        /// </exception>1083        /// <exception cref="ObjectDisposedException">1084        /// Object is disposed.1085        /// </exception>1086        [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]1087        public PSDataCollection<PSObject> Output1088        {1089            get1090            {1091                LoadJobStreams(); // for delayed loading1092                return _output;1093            }1094 1095            set1096            {1097                if (value == null)1098                {1099                    throw PSTraceSource.NewArgumentNullException("Output");1100                }1101 1102                lock (syncObject)1103                {1104                    AssertChangesAreAccepted();1105                    _outputOwner = false;1106                    _output = value;1107                    _jobStreamsLoaded = true;1108                }1109            }1110        }1111 1112        /// <summary>1113        /// Gets or sets the error buffer. Errors of job are written1114        /// into this buffer.1115        /// </summary>1116        /// <exception cref="ArgumentNullException">1117        /// Cannot set to a null value.1118        /// </exception>1119        /// <exception cref="ObjectDisposedException">1120        /// Object is disposed.1121        /// </exception>1122        [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]1123        public PSDataCollection<ErrorRecord> Error1124        {1125            get1126            {1127                LoadJobStreams(); // for delayed loading1128                return _error;1129            }1130 1131            set1132            {1133                if (value == null)1134                {1135                    throw PSTraceSource.NewArgumentNullException("Error");1136                }1137 1138                lock (syncObject)1139                {1140                    AssertChangesAreAccepted();1141                    _errorOwner = false;1142                    _error = value;1143                    _jobStreamsLoaded = true;1144                }1145            }1146        }1147 1148        /// <summary>1149        /// Gets or sets the progress buffer. Progress of job is written1150        /// into this buffer.1151        /// </summary>1152        /// <exception cref="ArgumentNullException">1153        /// Cannot set to a null value.1154        /// </exception>1155        /// <exception cref="ObjectDisposedException">1156        /// Object is disposed.1157        /// </exception>1158        [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]1159        public PSDataCollection<ProgressRecord> Progress1160        {1161            get1162            {1163                LoadJobStreams(); // for delayed loading1164                return _progress;1165            }1166 1167            set1168            {1169                if (value == null)1170                {1171                    throw PSTraceSource.NewArgumentNullException("Progress");1172                }1173 1174                lock (syncObject)1175                {1176                    AssertChangesAreAccepted();1177                    _progressOwner = false;1178                    _progress = value;1179                    _jobStreamsLoaded = true;1180                }1181            }1182        }1183 1184        /// <summary>1185        /// Gets or sets the verbose buffer. Verbose output of job is written to1186        /// this stream.1187        /// </summary>1188        /// <exception cref="ObjectDisposedException">1189        /// Object is disposed.1190        /// </exception>1191        [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]1192        public PSDataCollection<VerboseRecord> Verbose1193        {1194            get1195            {1196                LoadJobStreams(); // for delayed loading1197                return _verbose;1198            }1199 1200            set

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