Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
PowerShell.cs6192 linesDownload Raw Back to hostifaces
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System;5using System.Collections;6using System.Collections.Generic;7using System.Collections.ObjectModel;8using System.Diagnostics;9using System.Diagnostics.CodeAnalysis;10using System.Management.Automation;11using System.Management.Automation.Host;12using System.Management.Automation.Internal;13using System.Management.Automation.Runspaces;14using System.Management.Automation.Runspaces.Internal;15using System.Runtime.Serialization;16using System.Threading;17using System.Threading.Tasks;18 19using Microsoft.Management.Infrastructure;20using Microsoft.PowerShell.Telemetry;21 22using Dbg = System.Management.Automation.Diagnostics;23 24#pragma warning disable 1634, 1691 // Stops compiler from warning about unknown warnings25 26namespace System.Management.Automation27{28    #region Exceptions29 30    /// <summary>31    /// Defines exception which is thrown when state of the PowerShell is different32    /// from the expected state.33    /// </summary>34    public class InvalidPowerShellStateException : SystemException35    {36        /// <summary>37        /// Creates a new instance of InvalidPowershellStateException class.38        /// </summary>39        public InvalidPowerShellStateException()40        : base41        (StringUtil.Format(PowerShellStrings.InvalidPowerShellStateGeneral))42        {43        }44 45        /// <summary>46        /// Creates a new instance of InvalidPowershellStateException class.47        /// </summary>48        /// <param name="message">49        /// The error message that explains the reason for the exception.50        /// </param>51        public InvalidPowerShellStateException(string message)52            : base(message)53        {54        }55 56        /// <summary>57        /// Creates a new instance of InvalidPowershellStateException class.58        /// </summary>59        /// <param name="message">60        /// The error message that explains the reason for the exception.61        /// </param>62        /// <param name="innerException">63        /// The exception that is the cause of the current exception.64        /// </param>65        public InvalidPowerShellStateException(string message, Exception innerException)66            : base(message, innerException)67        {68        }69 70        /// <summary>71        /// Initializes a new instance of the InvalidPowerShellStateException and defines value of72        /// CurrentState.73        /// </summary>74        /// <param name="currentState">Current state of powershell.</param>75        internal InvalidPowerShellStateException(PSInvocationState currentState)76        : base77        (StringUtil.Format(PowerShellStrings.InvalidPowerShellStateGeneral))78        {79            _currState = currentState;80        }81 82        #region ISerializable Members83 84        // No need to implement GetObjectData85        // if all fields are static or [NonSerialized]86 87        /// <summary>88        /// Initializes a new instance of the InvalidPowerShellStateException89        /// class with serialized data.90        /// </summary>91        /// <param name="info">92        /// The <see cref="SerializationInfo"/> that holds the serialized object93        /// data about the exception being thrown.94        /// </param>95        /// <param name="context">96        /// The <see cref="StreamingContext"/> that contains contextual information97        /// about the source or destination.98        /// </param>99        [Obsolete("Legacy serialization support is deprecated since .NET 8", DiagnosticId = "SYSLIB0051")]100        protected101        InvalidPowerShellStateException(SerializationInfo info, StreamingContext context)102        {103            throw new NotSupportedException();104        }105 106        #endregion107 108        /// <summary>109        /// Gets CurrentState of the powershell.110        /// </summary>111        public PSInvocationState CurrentState112        {113            get114            {115                return _currState;116            }117        }118 119        /// <summary>120        /// State of powershell when exception was thrown.121        /// </summary>122        [NonSerialized]123        private readonly PSInvocationState _currState = 0;124    }125 126    #endregion127 128    #region PSInvocationState, PSInvocationStateInfo, PSInvocationStateChangedEventArgs129 130    /// <summary>131    /// Enumerated type defining the state of the PowerShell.132    /// </summary>133    public enum PSInvocationState134    {135        /// <summary>136        /// PowerShell has not been started.137        /// </summary>138        NotStarted = 0,139        /// <summary>140        /// PowerShell is executing.141        /// </summary>142        Running = 1,143        /// <summary>144        /// PowerShell is stoping execution.145        /// </summary>146        Stopping = 2,147        /// <summary>148        /// PowerShell is completed due to a stop request.149        /// </summary>150        Stopped = 3,151        /// <summary>152        /// PowerShell has completed executing a command.153        /// </summary>154        Completed = 4,155        /// <summary>156        /// PowerShell completed abnormally due to an error.157        /// </summary>158        Failed = 5,159        /// <summary>160        /// PowerShell is in disconnected state.161        /// </summary>162        Disconnected = 6163    }164 165    /// <summary>166    /// Enumerated type defining runspace modes for nested pipeline.167    /// </summary>168    public enum RunspaceMode169    {170        /// <summary>171        /// Use current runspace from the current thread of execution.172        /// </summary>173        CurrentRunspace = 0,174 175        /// <summary>176        /// Create new runspace.177        /// </summary>178        NewRunspace = 1179    }180 181    /// <summary>182    /// Type which has information about InvocationState and Exception183    /// associated with InvocationState.184    /// </summary>185    public sealed class PSInvocationStateInfo186    {187        #region Constructors188 189        /// <summary>190        /// Constructor for state changes with an optional error.191        /// </summary>192        /// <param name="state">The new state.</param>193        /// <param name="reason">A non-null exception if the state change was194        /// caused by an error,otherwise; null.195        /// </param>196        internal PSInvocationStateInfo(PSInvocationState state, Exception reason)197        {198            _executionState = state;199            _exceptionReason = reason;200        }201 202        /// <summary>203        /// Construct from PipelineStateInfo.204        /// </summary>205        /// <param name="pipelineStateInfo"></param>206        internal PSInvocationStateInfo(PipelineStateInfo pipelineStateInfo)207        {208            _executionState = (PSInvocationState)((int)pipelineStateInfo.State);209            _exceptionReason = pipelineStateInfo.Reason;210        }211 212        #endregion213 214        #region Public Properties215 216        /// <summary>217        /// The state of the PowerShell instance.218        /// </summary>219        /// <remarks>220        /// </remarks>221        public PSInvocationState State222        {223            get224            {225                return _executionState;226            }227        }228 229        /// <summary>230        /// The reason for the state change, if caused by an error.231        /// </summary>232        /// <remarks>233        /// The value of this property is non-null if the state234        /// changed due to an error. Otherwise, the value of this235        /// property is null.236        /// </remarks>237        public Exception Reason238        {239            get240            {241                return _exceptionReason;242            }243        }244 245        #endregion246 247        /// <summary>248        /// Clone the current instance.249        /// </summary>250        /// <returns>251        /// A copy of the current instance.252        /// </returns>253        internal PSInvocationStateInfo Clone()254        {255            return new PSInvocationStateInfo(256                _executionState,257                _exceptionReason258                );259        }260 261        #region Private data262 263        /// <summary>264        /// The current execution state.265        /// </summary>266        private readonly PSInvocationState _executionState;267 268        /// <summary>269        /// Non-null exception if the execution state change was due to an error.270        /// </summary>271        private readonly Exception _exceptionReason;272 273        #endregion274    }275 276    /// <summary>277    /// Event arguments passed to PowerShell state change handlers278    /// <see cref="PowerShell.InvocationStateChanged"/> event.279    /// </summary>280    public sealed class PSInvocationStateChangedEventArgs : EventArgs281    {282        #region Constructors283 284        /// <summary>285        /// Constructs PSInvocationStateChangedEventArgs from PSInvocationStateInfo.286        /// </summary>287        /// <param name="psStateInfo">288        /// state to raise the event with.289        /// </param>290        internal PSInvocationStateChangedEventArgs(PSInvocationStateInfo psStateInfo)291        {292            Dbg.Assert(psStateInfo != null, "caller should validate the parameter");293            InvocationStateInfo = psStateInfo;294        }295 296        #endregion297 298        #region Public Properties299 300        /// <summary>301        /// Information about current state of a PowerShell Instance.302        /// </summary>303        public PSInvocationStateInfo InvocationStateInfo { get; }304 305        #endregion306    }307 308    #endregion309 310    /// <summary>311    /// Settings to control command invocation.312    /// </summary>313    public sealed class PSInvocationSettings314    {315        #region Private Fields316 317        private PSHost _host;318 319        // the following are used to flow the identity to pipeline execution thread320 321        // Invokes a remote command and immediately disconnects, if transport layer322        // supports this operation.323 324        #endregion325 326        #region Constructors327 328        /// <summary>329        /// Default Constructor.330        /// </summary>331        public PSInvocationSettings()332        {333            this.ApartmentState = ApartmentState.Unknown;334            _host = null;335            RemoteStreamOptions = 0;336            AddToHistory = false;337            ErrorActionPreference = null;338        }339 340        #endregion341 342        /// <summary>343        /// ApartmentState of the thread in which the command344        /// is executed.345        /// </summary>346        public ApartmentState ApartmentState { get; set; }347 348        /// <summary>349        /// Host to use with the Runspace when the command is350        /// executed.351        /// </summary>352        public PSHost Host353        {354            get355            {356                return _host;357            }358 359            set360            {361                if (value == null)362                {363                    throw PSTraceSource.NewArgumentNullException("Host");364                }365 366                _host = value;367            }368        }369 370        /// <summary>371        /// Options for the Error, Warning, Verbose and Debug streams during remote calls.372        /// </summary>373        public RemoteStreamOptions RemoteStreamOptions { get; set; }374 375        /// <summary>376        /// Boolean which tells if the command is added to the history of the377        /// Runspace the command is executing in. By default this is false.378        /// </summary>379        public bool AddToHistory { get; set; }380 381        /// <summary>382        /// Determines how errors should be handled during batch command execution.383        /// </summary>384        public ActionPreference? ErrorActionPreference { get; set; }385 386        /// <summary>387        /// Used by Powershell remoting infrastructure to flow identity from calling thread to388        /// Pipeline Execution Thread.389        /// </summary>390        /// <remarks>391        /// Scenario: In the IIS hosting model, the calling thread is impersonated with a different392        /// identity than the process identity. However Pipeline Execution Thread always inherits393        /// process's identity and this will create problems related to security. In the IIS hosting394        /// model, we should honor calling threads identity.395        /// </remarks>396        public bool FlowImpersonationPolicy { get; set; }397 398        internal System.Security.Principal.WindowsIdentity WindowsIdentityToImpersonate { get; set; }399 400        /// <summary>401        /// When true, allows an unhandled flow control exceptions to402        /// propagate to a caller invoking the PowerShell object.403        /// </summary>404        public bool ExposeFlowControlExceptions405        {406            get;407            set;408        }409 410        /// <summary>411        /// Invokes a remote command and immediately disconnects, if the transport412        /// layer supports this operation.413        /// </summary>414        internal bool InvokeAndDisconnect { get; set; }415    }416 417    /// <summary>418    /// Batch execution context.419    /// </summary>420    internal class BatchInvocationContext421    {422        private readonly AutoResetEvent _completionEvent;423 424        /// <summary>425        /// Class constructor.426        /// </summary>427        /// <param name="command"></param>428        /// <param name="output"></param>429        internal BatchInvocationContext(PSCommand command, PSDataCollection<PSObject> output)430        {431            Command = command;432            Output = output;433            _completionEvent = new AutoResetEvent(false);434        }435 436        /// <summary>437        /// Invocation output.438        /// </summary>439        internal PSDataCollection<PSObject> Output { get; }440 441        /// <summary>442        /// Command to invoke.443        /// </summary>444        internal PSCommand Command { get; }445 446        /// <summary>447        /// Waits for the completion event.448        /// </summary>449        internal void Wait()450        {451            _completionEvent.WaitOne();452        }453 454        /// <summary>455        /// Signals the completion event.456        /// </summary>457        internal void Signal()458        {459            _completionEvent.Set();460        }461    }462 463    /// <summary>464    /// These flags control whether InvocationInfo is added to items in the Error, Warning, Verbose and Debug465    /// streams during remote calls.466    /// </summary>467    [Flags]468    public enum RemoteStreamOptions469    {470        /// <summary>471        /// If this flag is set, ErrorRecord will include an instance of InvocationInfo on remote calls.472        /// </summary>473        AddInvocationInfoToErrorRecord = 0x01,474 475        /// <summary>476        /// If this flag is set, WarningRecord will include an instance of InvocationInfo on remote calls.477        /// </summary>478        AddInvocationInfoToWarningRecord = 0x02,479 480        /// <summary>481        /// If this flag is set, DebugRecord will include an instance of InvocationInfo on remote calls.482        /// </summary>483        AddInvocationInfoToDebugRecord = 0x04,484 485        /// <summary>486        /// If this flag is set, VerboseRecord will include an instance of InvocationInfo on remote calls.487        /// </summary>488        AddInvocationInfoToVerboseRecord = 0x08,489 490        /// <summary>491        /// If this flag is set, ErrorRecord, WarningRecord, DebugRecord, and VerboseRecord will include an instance of InvocationInfo on remote calls.492        /// </summary>493        AddInvocationInfo = AddInvocationInfoToErrorRecord494                          | AddInvocationInfoToWarningRecord495                          | AddInvocationInfoToDebugRecord496                          | AddInvocationInfoToVerboseRecord497    }498 499    #region PowerShell AsyncResult500 501    /// <summary>502    /// Internal Async result type used by BeginInvoke() and BeginStop() overloads.503    /// </summary>504    internal sealed class PowerShellAsyncResult : AsyncResult505    {506        #region Private Data / Properties507 508        // used to track if this AsyncResult is created by a BeginInvoke operation or509        // a BeginStop operation.510 511        /// <summary>512        /// True if AsyncResult monitors Async BeginInvoke().513        /// false otherwise.514        /// </summary>515        internal bool IsAssociatedWithAsyncInvoke { get; }516 517        /// <summary>518        /// The output buffer for the asynchronous invoke.519        /// </summary>520        internal PSDataCollection<PSObject> Output { get; }521 522        #endregion523 524        #region Constructor525 526        /// <summary>527        /// Constructor.528        /// </summary>529        /// <param name="ownerId">530        /// Instance Id of the Powershell object creating this instance531        /// </param>532        /// <param name="callback">533        /// Callback to call when the async operation completes.534        /// </param>535        /// <param name="state">536        /// A user supplied state to call the "callback" with.537        /// </param>538        /// <param name="output">539        /// The output buffer to return from EndInvoke.540        /// </param>541        /// <param name="isCalledFromBeginInvoke">542        /// true if AsyncResult monitors BeginInvoke.543        /// false otherwise544        /// </param>545        internal PowerShellAsyncResult(Guid ownerId, AsyncCallback callback, object state, PSDataCollection<PSObject> output,546            bool isCalledFromBeginInvoke)547            : base(ownerId, callback, state)548        {549            IsAssociatedWithAsyncInvoke = isCalledFromBeginInvoke;550            Output = output;551        }552 553        #endregion554    }555 556    #endregion557 558    /// <summary>559    /// Represents a PowerShell command or script to execute against a560    /// Runspace(Pool) if provided, otherwise execute using a default561    /// Runspace. Provides access to different result buffers562    /// like output, error, debug, verbose, progress, warning, and information.563    ///564    /// Provides a simple interface to execute a powershell command:565    /// <code>566    ///    Powershell.Create().AddScript("get-process").Invoke();567    /// </code>568    /// The above statement creates a local runspace using default569    /// configuration, executes the command and then closes the runspace.570    ///571    /// Using RunspacePool property, the caller can provide the runspace572    /// where the command / script is executed.573    /// </summary>574    [SuppressMessage("Microsoft.Naming", "CA1724:TypeNamesShouldNotMatchNamespaces", Justification = "PowerShell is a valid type in SMAR namespace.")]575    public sealed class PowerShell : IDisposable576    {577        #region Private Fields578 579        private PSCommand _psCommand;580        // worker object which does the invoke581        private Worker _worker;582        private PowerShellAsyncResult _invokeAsyncResult;583        private PowerShellAsyncResult _stopAsyncResult;584        private PowerShellAsyncResult _batchAsyncResult;585        private PSInvocationSettings _batchInvocationSettings;586        private PSCommand _backupPSCommand;587        private object _rsConnection;588 589        private PSDataCollection<ErrorRecord> _errorBuffer;590 591        private bool _isDisposed;592        private readonly object _syncObject = new object();593 594        // client remote powershell if the powershell595        // is executed with a remote runspace pool596 597        private ConnectCommandInfo _connectCmdInfo;598        private bool _commandInvokedSynchronously = false;599        private bool _isBatching = false;600        private bool _stopBatchExecution = false;601 602        // Delegates for asynchronous invocation/termination of PowerShell commands603        private readonly Func<IAsyncResult, PSDataCollection<PSObject>> _endInvokeMethod;604        private readonly Action<IAsyncResult> _endStopMethod;605 606        #endregion607 608        #region Internal Constructors609 610        /// <summary>611        /// Constructs PowerShell.612        /// </summary>613        /// <param name="command">614        /// A PSCommand.615        /// </param>616        /// <param name="extraCommands">617        /// A list of extra commands to run618        /// </param>619        /// <param name="rsConnection">620        /// A Runspace or RunspacePool to refer while invoking the command.621        /// This can be null in which case a new runspace is created622        /// whenever Invoke* method is called.623        /// </param>624        private PowerShell(PSCommand command, Collection<PSCommand> extraCommands, object rsConnection)625        {626            Dbg.Assert(command != null, "command must not be null");627            ExtraCommands = extraCommands ?? new Collection<PSCommand>();628            RunningExtraCommands = false;629            _psCommand = command;630            _psCommand.Owner = this;631            RemoteRunspace remoteRunspace = rsConnection as RemoteRunspace;632            _rsConnection = remoteRunspace != null ? remoteRunspace.RunspacePool : rsConnection;633            InstanceId = Guid.NewGuid();634            InvocationStateInfo = new PSInvocationStateInfo(PSInvocationState.NotStarted, null);635            OutputBuffer = null;636            OutputBufferOwner = true;637            _errorBuffer = new PSDataCollection<ErrorRecord>();638            ErrorBufferOwner = true;639            InformationalBuffers = new PSInformationalBuffers(InstanceId);640            Streams = new PSDataStreams(this);641            _endInvokeMethod = EndInvoke;642            _endStopMethod = EndStop;643            ApplicationInsightsTelemetry.SendTelemetryMetric(TelemetryType.PowerShellCreate, "create");644        }645 646        /// <summary>647        /// Constructs a PowerShell instance in the disconnected start state with648        /// the provided remote command connect information and runspace(pool) objects.649        /// </summary>650        /// <param name="connectCmdInfo">Remote command connect information.</param>651        /// <param name="rsConnection">Remote Runspace or RunspacePool object.</param>652        internal PowerShell(ConnectCommandInfo connectCmdInfo, object rsConnection)653            : this(new PSCommand(), null, rsConnection)654        {655            ExtraCommands = new Collection<PSCommand>();656            RunningExtraCommands = false;657            AddCommand(connectCmdInfo.Command);658            _connectCmdInfo = connectCmdInfo;659 660            // The command ID is passed to the PSRP layer through the PowerShell instanceID.661            InstanceId = _connectCmdInfo.CommandId;662 663            InvocationStateInfo = new PSInvocationStateInfo(PSInvocationState.Disconnected, null);664 665            if (rsConnection is RemoteRunspace)666            {667                _runspace = rsConnection as Runspace;668                _runspacePool = ((RemoteRunspace)rsConnection).RunspacePool;669            }670            else if (rsConnection is RunspacePool)671            {672                _runspacePool = (RunspacePool)rsConnection;673            }674 675            Dbg.Assert(_runspacePool != null, "Invalid rsConnection parameter>");676            RemotePowerShell = new ClientRemotePowerShell(this, _runspacePool.RemoteRunspacePoolInternal);677        }678 679        /// <summary>680        /// </summary>681        /// <param name="inputstream"></param>682        /// <param name="outputstream"></param>683        /// <param name="errorstream"></param>684        /// <param name="runspacePool"></param>685        internal PowerShell(ObjectStreamBase inputstream,686            ObjectStreamBase outputstream, ObjectStreamBase errorstream, RunspacePool runspacePool)687        {688            ExtraCommands = new Collection<PSCommand>();689            RunningExtraCommands = false;690            _rsConnection = runspacePool;691            InstanceId = Guid.NewGuid();692            InvocationStateInfo = new PSInvocationStateInfo(PSInvocationState.NotStarted, null);693            InformationalBuffers = new PSInformationalBuffers(InstanceId);694            Streams = new PSDataStreams(this);695 696            PSDataCollectionStream<PSObject> outputdatastream = (PSDataCollectionStream<PSObject>)outputstream;697            OutputBuffer = outputdatastream.ObjectStore;698 699            PSDataCollectionStream<ErrorRecord> errordatastream = (PSDataCollectionStream<ErrorRecord>)errorstream;700            _errorBuffer = errordatastream.ObjectStore;701 702            if (runspacePool != null && runspacePool.RemoteRunspacePoolInternal != null)703            {704                RemotePowerShell = new ClientRemotePowerShell(this, runspacePool.RemoteRunspacePoolInternal);705            }706 707            _endInvokeMethod = EndInvoke;708            _endStopMethod = EndStop;709        }710 711        /// <summary>712        /// Creates a PowerShell object in the disconnected start state and with a ConnectCommandInfo object713        /// parameter that specifies what remote command to associate with this PowerShell when it is connected.714        /// </summary>715        /// <param name="connectCmdInfo"></param>716        /// <param name="inputstream"></param>717        /// <param name="outputstream"></param>718        /// <param name="errorstream"></param>719        /// <param name="runspacePool"></param>720        internal PowerShell(ConnectCommandInfo connectCmdInfo, ObjectStreamBase inputstream, ObjectStreamBase outputstream,721            ObjectStreamBase errorstream, RunspacePool runspacePool)722            : this(inputstream, outputstream, errorstream, runspacePool)723        {724            ExtraCommands = new Collection<PSCommand>();725            RunningExtraCommands = false;726            _psCommand = new PSCommand();727            _psCommand.Owner = this;728            _runspacePool = runspacePool;729 730            AddCommand(connectCmdInfo.Command);731            _connectCmdInfo = connectCmdInfo;732 733            // The command ID is passed to the PSRP layer through the PowerShell instanceID.734            InstanceId = _connectCmdInfo.CommandId;735 736            InvocationStateInfo = new PSInvocationStateInfo(PSInvocationState.Disconnected, null);737 738            RemotePowerShell = new ClientRemotePowerShell(this, runspacePool.RemoteRunspacePoolInternal);739        }740 741        /// <summary>742        /// Sets the command collection in this powershell.743        /// </summary>744        /// <remarks>This method will be called by RemotePipeline745        /// before it begins execution. This method is used to set746        /// the command collection of the remote pipeline as the747        /// command collection of the underlying powershell</remarks>748        internal void InitForRemotePipeline(CommandCollection command, ObjectStreamBase inputstream,749            ObjectStreamBase outputstream, ObjectStreamBase errorstream, PSInvocationSettings settings, bool redirectShellErrorOutputPipe)750        {751            Dbg.Assert(command != null, "A command collection need to be specified");752 753            _psCommand = new PSCommand(command[0]);754            _psCommand.Owner = this;755 756            for (int i = 1; i < command.Count; i++)757            {758                AddCommand(command[i]);759            }760 761            RedirectShellErrorOutputPipe = redirectShellErrorOutputPipe;762 763            // create the client remote powershell for remoting764            // communications765            RemotePowerShell ??= new ClientRemotePowerShell(this, ((RunspacePool)_rsConnection).RemoteRunspacePoolInternal);766 767            // If we get here, we don't call 'Invoke' or any of it's friends on 'this', instead we serialize 'this' in PowerShell.ToPSObjectForRemoting.768            // Without the following two steps, we'll be missing the 'ExtraCommands' on the serialized instance of 'this'.769            // This is the last possible chance to call set up for batching as we will indirectly call ToPSObjectForRemoting770            // in the call to ClientRemotePowerShell.Initialize (which happens just below.)771            DetermineIsBatching();772 773            if (_isBatching)774            {775                SetupAsyncBatchExecution();776            }777 778            RemotePowerShell.Initialize(inputstream, outputstream,779                errorstream, InformationalBuffers, settings);780        }781 782        /// <summary>783        /// Initialize PowerShell object for connection to remote command.784        /// </summary>785        /// <param name="inputstream">Input stream.</param>786        /// <param name="outputstream">Output stream.</param>787        /// <param name="errorstream">Error stream.</param>788        /// <param name="settings">Settings information.</param>789        /// <param name="redirectShellErrorOutputPipe">Redirect error output.</param>790        internal void InitForRemotePipelineConnect(ObjectStreamBase inputstream, ObjectStreamBase outputstream,791            ObjectStreamBase errorstream, PSInvocationSettings settings, bool redirectShellErrorOutputPipe)792        {793            // The remotePowerShell and DSHandler cannot be initialized with a disconnected runspace.794            // Make sure the associated runspace is valid and connected.795            CheckRunspacePoolAndConnect();796 797            if (InvocationStateInfo.State != PSInvocationState.Disconnected)798            {799                throw new InvalidPowerShellStateException(InvocationStateInfo.State);800            }801 802            RedirectShellErrorOutputPipe = redirectShellErrorOutputPipe;803 804            RemotePowerShell ??= new ClientRemotePowerShell(this, ((RunspacePool)_rsConnection).RemoteRunspacePoolInternal);805 806            if (!RemotePowerShell.Initialized)807            {808                RemotePowerShell.Initialize(inputstream, outputstream, errorstream, InformationalBuffers, settings);809            }810        }811 812        #endregion813 814        #region Construction Factory815 816        /// <summary>817        /// Constructs an empty PowerShell instance; a script or command must be added before invoking this instance.818        /// </summary>819        /// <returns>820        /// An instance of PowerShell.821        /// </returns>822        public static PowerShell Create()823        {824            return new PowerShell(new PSCommand(), null, null);825        }826 827        /// <summary>828        /// Constructs an empty PowerShell instance; a script or command must be added before invoking this instance.829        /// </summary>830        /// <param name="runspace">Runspace mode.</param>831        /// <returns>An instance of PowerShell.</returns>832        public static PowerShell Create(RunspaceMode runspace)833        {834            PowerShell result = null;835 836            switch (runspace)837            {838                case RunspaceMode.CurrentRunspace:839                    if (Runspace.DefaultRunspace == null)840                    {841                        throw new InvalidOperationException(PowerShellStrings.NoDefaultRunspaceForPSCreate);842                    }843 844                    result = new PowerShell(new PSCommand(), null, Runspace.DefaultRunspace);845                    result.IsChild = true;846                    result.IsNested = true;847                    result.IsRunspaceOwner = false;848                    result._runspace = Runspace.DefaultRunspace;849                    break;850                case RunspaceMode.NewRunspace:851                    result = new PowerShell(new PSCommand(), null, null);852                    break;853            }854 855            return result;856        }857 858        /// <summary>859        /// Constructs an empty PowerShell instance; a script or command must be added before invoking this instance.860        /// </summary>861        /// <param name="initialSessionState">InitialSessionState with which to create the runspace.</param>862        /// <returns>An instance of PowerShell.</returns>863        public static PowerShell Create(InitialSessionState initialSessionState)864        {865            PowerShell result = Create();866 867            result.Runspace = RunspaceFactory.CreateRunspace(initialSessionState);868            result.Runspace.Open();869 870            return result;871        }872 873        /// <summary>874        /// Constructs an empty PowerShell instance and associates it with the provided875        /// Runspace; a script or command must be added before invoking this instance.876        /// </summary>877        /// <param name="runspace">Runspace in which to invoke commands.</param>878        /// <returns>An instance of PowerShell.</returns>879        /// <remarks>880        /// The required Runspace argument is accepted no matter what state it is in.881        /// Leaving Runspace state management to the caller allows them to open their882        /// runspace in whatever manner is most appropriate for their application883        /// (in another thread while this instance of the PowerShell class is being884        /// instantiated, for example).885        /// </remarks>886        public static PowerShell Create(Runspace runspace)887        {888            if (runspace == null)889            {890                throw new PSArgumentNullException(nameof(runspace));891            }892 893            PowerShell result = Create();894            result.Runspace = runspace;895 896            return result;897        }898 899        /// <summary>900        /// Creates a nested powershell within the current instance.901        /// Nested PowerShell is used to do simple operations like checking state902        /// of a variable while another command is using the runspace.903        ///904        /// Nested PowerShell should be invoked from the same thread as the parent905        /// PowerShell invocation thread. So effectively the parent Powershell906        /// invocation thread is blocked until nested invoke() operation is907        /// complete.908        ///909        /// Implement PSHost.EnterNestedPrompt to perform invoke() operation on the910        /// nested powershell.911        /// </summary>912        /// <exception cref="InvalidOperationException">913        /// 1. State of powershell instance is not valid to create a nested powershell instance.914        /// Nested PowerShell should be created only for a running powershell instance.915        /// </exception>916        [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "ps", Justification = "ps represents PowerShell and is used at many places.")]917        public PowerShell CreateNestedPowerShell()918        {919            if ((_worker != null) && (_worker.CurrentlyRunningPipeline != null))920            {921                PowerShell result = new PowerShell(new PSCommand(),922                    null, _worker.CurrentlyRunningPipeline.Runspace);923                result.IsNested = true;924                return result;925            }926 927            throw PSTraceSource.NewInvalidOperationException(PowerShellStrings.InvalidStateCreateNested);928        }929 930        /// <summary>931        /// Method needed when deserializing PowerShell object coming from a RemoteDataObject.932        /// </summary>933        /// <param name="isNested">Indicates if PowerShell object is nested.</param>934        /// <param name="psCommand">Commands that the PowerShell pipeline is built of.</param>935        /// <param name="extraCommands">Extra commands to run.</param>936        private static PowerShell Create(bool isNested, PSCommand psCommand, Collection<PSCommand> extraCommands)937        {938            PowerShell powerShell = new PowerShell(psCommand, extraCommands, null);939            powerShell.IsNested = isNested;940            return powerShell;941        }942 943        #endregion944 945        #region Command / Parameter Construction946 947        /// <summary>948        /// Add a cmdlet to construct a command pipeline.949        /// For example, to construct a command string "Get-Process | Sort-Object",950        ///     <code>951        ///         PowerShell shell = PowerShell.Create()952        ///             .AddCommand("Get-Process")953        ///             .AddCommand("Sort-Object");954        ///     </code>955        /// </summary>956        /// <param name="cmdlet">957        /// A string representing cmdlet.958        /// </param>959        /// <returns>960        /// A PowerShell instance with <paramref name="cmdlet"/> added.961        /// </returns>962        /// <remarks>963        /// This method is not thread safe.964        /// </remarks>965        /// <exception cref="ArgumentNullException">966        /// cmdlet is null.967        /// </exception>968        /// <exception cref="InvalidPowerShellStateException">969        /// Powershell instance cannot be changed in its970        /// current state.971        /// </exception>972        /// <exception cref="ObjectDisposedException">973        /// Object is disposed.974        /// </exception>975        public PowerShell AddCommand(string cmdlet)976        {977            lock (_syncObject)978            {979                AssertChangesAreAccepted();980 981                _psCommand.AddCommand(cmdlet);982 983                return this;984            }985        }986 987        /// <summary>988        /// Add a cmdlet to construct a command pipeline.989        /// For example, to construct a command string "Get-Process | Sort-Object",990        ///     <code>991        ///         PowerShell shell = PowerShell.Create()992        ///             .AddCommand("Get-Process", true)993        ///             .AddCommand("Sort-Object", true);994        ///     </code>995        /// </summary>996        /// <param name="cmdlet">997        /// A string representing cmdlet.998        /// </param>999        /// <param name="useLocalScope">1000        /// if true local scope is used to run the script command.1001        /// </param>1002        /// <returns>1003        /// A PowerShell instance with <paramref name="cmdlet"/> added.1004        /// </returns>1005        /// <remarks>1006        /// This method is not thread safe.1007        /// </remarks>1008        /// <exception cref="ArgumentNullException">1009        /// cmdlet is null.1010        /// </exception>1011        /// <exception cref="InvalidPowerShellStateException">1012        /// Powershell instance cannot be changed in its1013        /// current state.1014        /// </exception>1015        /// <exception cref="ObjectDisposedException">1016        /// Object is disposed.1017        /// </exception>1018        public PowerShell AddCommand(string cmdlet, bool useLocalScope)1019        {1020            lock (_syncObject)1021            {1022                AssertChangesAreAccepted();1023 1024                _psCommand.AddCommand(cmdlet, useLocalScope);1025 1026                return this;1027            }1028        }1029 1030        /// <summary>1031        /// Add a piece of script to construct a command pipeline.1032        /// For example, to construct a command string "Get-Process | ForEach-Object { $_.Name }"1033        ///     <code>1034        ///         PowerShell shell = PowerShell.Create()1035        ///             .AddScript("Get-Process | ForEach-Object { $_.Name }");1036        ///     </code>1037        /// </summary>1038        /// <param name="script">1039        /// A string representing a script.1040        /// </param>1041        /// <returns>1042        /// A PowerShell instance with <paramref name="command"/> added.1043        /// </returns>1044        /// <remarks>1045        /// This method is not thread-safe.1046        /// </remarks>1047        /// <exception cref="ArgumentNullException">1048        /// command is null.1049        /// </exception>1050        /// <exception cref="InvalidPowerShellStateException">1051        /// Powershell instance cannot be changed in its1052        /// current state.1053        /// </exception>1054        /// <exception cref="ObjectDisposedException">1055        /// Object is disposed.1056        /// </exception>1057        public PowerShell AddScript(string script)1058        {1059            lock (_syncObject)1060            {1061                AssertChangesAreAccepted();1062 1063                _psCommand.AddScript(script);1064 1065                return this;1066            }1067        }1068 1069        /// <summary>1070        /// Add a piece of script to construct a command pipeline.1071        /// For example, to construct a command string "Get-Process | ForEach-Object { $_.Name }"1072        ///     <code>1073        ///         PowerShell shell = PowerShell.Create()1074        ///             .AddScript("Get-Process | ForEach-Object { $_.Name }", true);1075        ///     </code>1076        /// </summary>1077        /// <param name="script">1078        /// A string representing a script.1079        /// </param>1080        /// <param name="useLocalScope">1081        /// if true local scope is used to run the script command.1082        /// </param>1083        /// <returns>1084        /// A PowerShell instance with <paramref name="command"/> added.1085        /// </returns>1086        /// <remarks>1087        /// This method is not thread-safe.1088        /// </remarks>1089        /// <exception cref="ArgumentNullException">1090        /// command is null.1091        /// </exception>1092        /// <exception cref="InvalidPowerShellStateException">1093        /// Powershell instance cannot be changed in its1094        /// current state.1095        /// </exception>1096        /// <exception cref="ObjectDisposedException">1097        /// Object is disposed.1098        /// </exception>1099        public PowerShell AddScript(string script, bool useLocalScope)1100        {1101            lock (_syncObject)1102            {1103                AssertChangesAreAccepted();1104 1105                _psCommand.AddScript(script, useLocalScope);1106 1107                return this;1108            }1109        }1110 1111        /// <summary>1112        /// Add a <see cref="Command"/> element to the current command1113        /// pipeline.1114        /// </summary>1115        /// <param name="command">1116        /// Command to add.1117        /// </param>1118        /// <returns>1119        /// A PSCommand instance with <paramref name="command"/> added.1120        /// </returns>1121        /// <remarks>1122        /// This method is not thread-safe.1123        /// </remarks>1124        /// <exception cref="ArgumentNullException">1125        /// command is null.1126        /// </exception>1127        /// <exception cref="InvalidPowerShellStateException">1128        /// Powershell instance cannot be changed in its1129        /// current state.1130        /// </exception>1131        /// <exception cref="ObjectDisposedException">1132        /// Object is disposed.1133        /// </exception>1134        internal PowerShell AddCommand(Command command)1135        {1136            lock (_syncObject)1137            {1138                AssertChangesAreAccepted();1139 1140                _psCommand.AddCommand(command);1141 1142                return this;1143            }1144        }1145 1146        /// <summary>1147        /// CommandInfo object for the command to add.1148        /// </summary>1149        /// <param name="commandInfo">The CommandInfo object for the command to add.</param>1150        /// <returns>1151        /// A PSCommand instance with the command added.1152        /// </returns>1153        /// <remarks>1154        /// This method is not thread-safe.1155        /// </remarks>1156        /// <exception cref="ArgumentNullException">1157        /// command is null.1158        /// </exception>1159        /// <exception cref="InvalidPowerShellStateException">1160        /// Powershell instance cannot be changed in its1161        /// current state.1162        /// </exception>1163        /// <exception cref="ObjectDisposedException">1164        /// Object is disposed.1165        /// </exception>1166        public PowerShell AddCommand(CommandInfo commandInfo)1167        {1168            if (commandInfo == null)1169            {1170                throw PSTraceSource.NewArgumentNullException(nameof(commandInfo));1171            }1172 1173            Command cmd = new Command(commandInfo);1174            _psCommand.AddCommand(cmd);1175            return this;1176        }1177 1178        /// <summary>1179        /// Add a parameter to the last added command.1180        /// For example, to construct a command string "Get-Process | Select-Object -Property Name"1181        ///     <code>1182        ///         PowerShell shell = PowerShell.Create()1183        ///             .AddCommand("Get-Process")1184        ///             .AddCommand("Select-Object").AddParameter("Property", "Name");1185        ///     </code>1186        /// </summary>1187        /// <param name="parameterName">1188        /// Name of the parameter.1189        /// </param>1190        /// <param name="value">1191        /// Value for the parameter.1192        /// </param>1193        /// <returns>1194        /// A PowerShell instance with <paramref name="parameterName"/> added1195        /// to the parameter list of the last command.1196        /// </returns>1197        /// <remarks>1198        /// This method is not thread safe.1199        /// </remarks>1200        /// <exception cref="ArgumentException">

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