Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
StartJob.cs824 linesDownload Raw Back to commands
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System;5using System.Collections;6using System.Collections.Generic;7using System.Diagnostics.CodeAnalysis;8using System.IO;9using System.Management.Automation;10using System.Management.Automation.Internal;11using System.Management.Automation.Remoting;12using System.Management.Automation.Runspaces;13using System.Management.Automation.Security;14 15namespace Microsoft.PowerShell.Commands16{17    /// <summary>18    /// This cmdlet start invocation of jobs in background.19    /// </summary>20    [Cmdlet(VerbsLifecycle.Start, "Job", DefaultParameterSetName = StartJobCommand.ComputerNameParameterSet, HelpUri = "https://go.microsoft.com/fwlink/?LinkID=2096796")]21    [OutputType(typeof(PSRemotingJob))]22    public class StartJobCommand : PSExecutionCmdlet, IDisposable23    {24        #region Private members25 26        private static readonly string s_startJobType = "BackgroundJob";27 28        #endregion29 30        #region Parameters31 32        private const string DefinitionNameParameterSet = "DefinitionName";33 34        /// <summary>35        /// JobDefinition Name.36        /// </summary>37        [Parameter(Position = 0, Mandatory = true,38                   ParameterSetName = StartJobCommand.DefinitionNameParameterSet)]39        [ValidateTrustedData]40        [ValidateNotNullOrEmpty]41        public string DefinitionName42        {43            get { return _definitionName; }44 45            set { _definitionName = value; }46        }47 48        private string _definitionName;49 50        /// <summary>51        /// JobDefinition file path.52        /// </summary>53        [Parameter(Position = 1,54                   ParameterSetName = StartJobCommand.DefinitionNameParameterSet)]55        [ValidateNotNullOrEmpty]56        public string DefinitionPath57        {58            get { return _definitionPath; }59 60            set { _definitionPath = value; }61        }62 63        private string _definitionPath;64 65        /// <summary>66        /// Job SourceAdapter type for this job definition.67        /// </summary>68        [Parameter(Position = 2,69            ParameterSetName = StartJobCommand.DefinitionNameParameterSet)]70        [ValidateNotNullOrEmpty]71        [SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods")]72        public string Type73        {74            get { return _definitionType; }75 76            set { _definitionType = value; }77        }78 79        private string _definitionType;80 81        /// <summary>82        /// Friendly name for this job object.83        /// </summary>84        [Parameter(ValueFromPipelineByPropertyName = true,85                   ParameterSetName = StartJobCommand.FilePathComputerNameParameterSet)]86        [Parameter(ValueFromPipelineByPropertyName = true,87                   ParameterSetName = StartJobCommand.ComputerNameParameterSet)]88        [Parameter(ValueFromPipelineByPropertyName = true,89                   ParameterSetName = StartJobCommand.LiteralFilePathComputerNameParameterSet)]90        public virtual string Name91        {92            get93            {94                return _name;95            }96 97            set98            {99                if (!string.IsNullOrEmpty(value))100                {101                    _name = value;102                }103            }104        }105 106        private string _name;107 108        /// <summary>109        /// Command to execute specified as a string. This can be a single110        /// cmdlet, an expression or anything that can be internally111        /// converted into a ScriptBlock.112        /// </summary>113        /// <remarks>This is used in the in process case with a114        /// "ValueFromPipelineProperty" enabled in order to maintain115        /// compatibility with v1.0</remarks>116        [Parameter(Position = 0,117                   Mandatory = true,118                   ParameterSetName = StartJobCommand.ComputerNameParameterSet)]119        [ValidateTrustedData]120        [Alias("Command")]121        public override ScriptBlock ScriptBlock122        {123            get124            {125                return base.ScriptBlock;126            }127 128            set129            {130                base.ScriptBlock = value;131            }132        }133 134        #region Suppress PSRemotingBaseCmdlet parameters135 136        // suppress all the parameters from PSRemotingBaseCmdlet137        // which should not be part of Start-PSJob138 139        /// <summary>140        /// Overriding to suppress this parameter.141        /// </summary>142        public override PSSession[] Session143        {144            get145            {146                return null;147            }148        }149 150        /// <summary>151        /// Overriding to suppress this parameter.152        /// </summary>153        public override string[] ComputerName154        {155            get156            {157                return null;158            }159        }160 161        /// <summary>162        /// Not used for OutOfProc jobs.  Suppressing this parameter.163        /// </summary>164        public override SwitchParameter EnableNetworkAccess165        {166            get { return false; }167        }168 169        /// <summary>170        /// Suppress SSHTransport.171        /// </summary>172        public override SwitchParameter SSHTransport173        {174            get { return false; }175        }176 177        /// <summary>178        /// Suppress SSHConnection.179        /// </summary>180        public override Hashtable[] SSHConnection181        {182            get { return null; }183        }184 185        /// <summary>186        /// Suppress UserName.187        /// </summary>188        public override string UserName189        {190            get { return null; }191        }192 193        /// <summary>194        /// Suppress KeyFilePath.195        /// </summary>196        public override string KeyFilePath197        {198            get { return null; }199        }200 201        /// <summary>202        /// Suppress HostName.203        /// </summary>204        public override string[] HostName205        {206            get { return null; }207        }208 209        /// <summary>210        /// Suppress Subsystem.211        /// </summary>212        public override string Subsystem213        {214            get { return null; }215        }216 217        #endregion218 219        /// <summary>220        /// Credential to use for this job.221        /// </summary>222        [Parameter(ParameterSetName = StartJobCommand.FilePathComputerNameParameterSet)]223        [Parameter(ParameterSetName = StartJobCommand.ComputerNameParameterSet)]224        [Parameter(ParameterSetName = StartJobCommand.LiteralFilePathComputerNameParameterSet)]225        [Credential]226        public override PSCredential Credential227        {228            get229            {230                return base.Credential;231            }232 233            set234            {235                base.Credential = value;236            }237        }238 239        /// <summary>240        /// Overriding to suppress this parameter.241        /// </summary>242        public override int Port243        {244            get245            {246                return 0;247            }248        }249 250        /// <summary>251        /// Overriding to suppress this parameter.252        /// </summary>253        public override SwitchParameter UseSSL254        {255            get256            {257                return false;258            }259        }260 261        /// <summary>262        /// Overriding to suppress this parameter.263        /// </summary>264        public override string ConfigurationName265        {266            get267            {268                return base.ConfigurationName;269            }270 271            set272            {273                base.ConfigurationName = value;274            }275        }276 277        /// <summary>278        /// Overriding to suppress this parameter.279        /// </summary>280        public override Int32 ThrottleLimit281        {282            get283            {284                return 0;285            }286        }287 288        /// <summary>289        /// Overriding to suppress this parameter.290        /// </summary>291        public override string ApplicationName292        {293            get294            {295                return null;296            }297        }298 299        /// <summary>300        /// Overriding to suppress this parameter.301        /// </summary>302        public override Uri[] ConnectionUri303        {304            get305            {306                return null;307            }308        }309 310        /// <summary>311        /// Filepath to execute as a script.312        /// </summary>313        [Parameter(314            Position = 0,315            Mandatory = true,316            ParameterSetName = StartJobCommand.FilePathComputerNameParameterSet)]317        [ValidateTrustedData]318        public override string FilePath319        {320            get321            {322                return base.FilePath;323            }324 325            set326            {327                base.FilePath = value;328            }329        }330 331        /// <summary>332        /// Literal Filepath to execute as a script.333        /// </summary>334        [Parameter(335            Mandatory = true,336            ParameterSetName = StartJobCommand.LiteralFilePathComputerNameParameterSet)]337        [ValidateTrustedData]338        [Alias("PSPath", "LP")]339        public string LiteralPath340        {341            get342            {343                return base.FilePath;344            }345 346            set347            {348                base.FilePath = value;349                base.IsLiteralPath = true;350            }351        }352 353        /// <summary>354        /// Use basic authentication to authenticate the user.355        /// </summary>356        [Parameter(ParameterSetName = StartJobCommand.FilePathComputerNameParameterSet)]357        [Parameter(ParameterSetName = StartJobCommand.ComputerNameParameterSet)]358        [Parameter(ParameterSetName = StartJobCommand.LiteralFilePathComputerNameParameterSet)]359        public override AuthenticationMechanism Authentication360        {361            get362            {363                return base.Authentication;364            }365 366            set367            {368                base.Authentication = value;369            }370        }371 372        /// <summary>373        /// Overriding to suppress this parameter.374        /// </summary>375        public override string CertificateThumbprint376        {377            get378            {379                return base.CertificateThumbprint;380            }381 382            set383            {384                base.CertificateThumbprint = value;385            }386        }387 388        /// <summary>389        /// Overriding to suppress this parameter.390        /// </summary>391        public override SwitchParameter AllowRedirection392        {393            get394            {395                return false;396            }397        }398 399        /// <summary>400        /// Overriding to suppress this parameter.401        /// </summary>402        public override Guid[] VMId403        {404            get405            {406                return null;407            }408        }409 410        /// <summary>411        /// Overriding to suppress this parameter.412        /// </summary>413        public override string[] VMName414        {415            get416            {417                return null;418            }419        }420 421        /// <summary>422        /// Overriding to suppress this parameter.423        /// </summary>424        public override string[] ContainerId425        {426            get427            {428                return null;429            }430        }431 432        /// <summary>433        /// Overriding to suppress this parameter.434        /// </summary>435        public override SwitchParameter RunAsAdministrator436        {437            get438            {439                return false;440            }441        }442 443        /// <summary>444        /// Extended Session Options for controlling the session creation. Use445        /// "New-WSManSessionOption" cmdlet to supply value for this parameter.446        /// </summary>447        /// <remarks>448        /// This is not declared as a Parameter for Start-PSJob as this is not449        /// used for background jobs.450        /// </remarks>451        public override PSSessionOption SessionOption452        {453            get454            {455                return base.SessionOption;456            }457 458            set459            {460                base.SessionOption = value;461            }462        }463 464        /// <summary>465        /// Script that is used to initialize the background job.466        /// </summary>467        [Parameter(Position = 1,468                   ParameterSetName = StartJobCommand.FilePathComputerNameParameterSet)]469        [Parameter(Position = 1,470                   ParameterSetName = StartJobCommand.ComputerNameParameterSet)]471        [Parameter(Position = 1,472                   ParameterSetName = StartJobCommand.LiteralFilePathComputerNameParameterSet)]473        [ValidateTrustedData]474        public virtual ScriptBlock InitializationScript475        {476            get { return _initScript; }477 478            set { _initScript = value; }479        }480 481        private ScriptBlock _initScript;482 483        /// <summary>484        /// Gets or sets an initial working directory for the powershell background job.485        /// </summary>486        [Parameter]487        [ValidateNotNullOrWhiteSpace]488        public string WorkingDirectory { get; set; }489 490        /// <summary>491        /// Launches the background job as a 32-bit process. This can be used on492        /// 64-bit systems to launch a 32-bit wow process for the background job.493        /// </summary>494        [Parameter(ParameterSetName = StartJobCommand.FilePathComputerNameParameterSet)]495        [Parameter(ParameterSetName = StartJobCommand.ComputerNameParameterSet)]496        [Parameter(ParameterSetName = StartJobCommand.LiteralFilePathComputerNameParameterSet)]497        public virtual SwitchParameter RunAs32 { get; set; }498 499        /// <summary>500        /// Powershell Version to execute the background job.501        /// </summary>502        [Parameter(ParameterSetName = StartJobCommand.FilePathComputerNameParameterSet)]503        [Parameter(ParameterSetName = StartJobCommand.ComputerNameParameterSet)]504        [Parameter(ParameterSetName = StartJobCommand.LiteralFilePathComputerNameParameterSet)]505        [ValidateNotNullOrEmpty]506        public virtual Version PSVersion507        {508            get509            {510                return _psVersion;511            }512 513            set514            {515                // PSVersion value can only be 5.1 for Start-Job.516                if (!(value.Major == 5 && value.Minor == 1))517                {518                    throw new ArgumentException(519                        StringUtil.Format(RemotingErrorIdStrings.PSVersionParameterOutOfRange, value, "PSVersion"));520                }521 522                _psVersion = value;523            }524        }525 526        private Version _psVersion;527 528        /// <summary>529        /// InputObject.530        /// </summary>531        [Parameter(ValueFromPipeline = true,532                   ParameterSetName = StartJobCommand.FilePathComputerNameParameterSet)]533        [Parameter(ValueFromPipeline = true,534                   ParameterSetName = StartJobCommand.ComputerNameParameterSet)]535        [Parameter(ValueFromPipeline = true,536                   ParameterSetName = StartJobCommand.LiteralFilePathComputerNameParameterSet)]537        [ValidateTrustedData]538        public override PSObject InputObject539        {540            get { return base.InputObject; }541 542            set { base.InputObject = value; }543        }544 545        /// <summary>546        /// ArgumentList.547        /// </summary>548        [Parameter(ParameterSetName = StartJobCommand.FilePathComputerNameParameterSet)]549        [Parameter(ParameterSetName = StartJobCommand.ComputerNameParameterSet)]550        [Parameter(ParameterSetName = StartJobCommand.LiteralFilePathComputerNameParameterSet)]551        [ValidateTrustedData]552        [Alias("Args")]553        [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]554        public override object[] ArgumentList555        {556            get { return base.ArgumentList; }557 558            set { base.ArgumentList = value; }559        }560 561        #endregion Parameters562 563        #region Overrides564 565        /// <summary>566        /// 1. Set the throttling limit and reset operations complete567        /// 2. Create helper objects568        /// 3. For async case, write the async result object down the569        ///    pipeline.570        /// </summary>571        protected override void BeginProcessing()572        {573            if (!File.Exists(PowerShellProcessInstance.PwshExePath))574            {575                // The pwsh executable file is not found under $PSHOME.576                // This means that PowerShell is currently being hosted in another application,577                // and 'Start-Job' is not supported by design in that scenario.578                string message = StringUtil.Format(579                    RemotingErrorIdStrings.IPCPwshExecutableNotFound,580                    PowerShellProcessInstance.PwshExePath);581 582                var errorRecord = new ErrorRecord(583                    new PSNotSupportedException(message),584                    "IPCPwshExecutableNotFound",585                    ErrorCategory.NotInstalled,586                    PowerShellProcessInstance.PwshExePath);587 588                ThrowTerminatingError(errorRecord);589            }590 591            if (RunAs32.IsPresent && Environment.Is64BitProcess)592            {593                // We cannot start a 32-bit 'pwsh' process from a 64-bit 'pwsh' installation.594                string message = RemotingErrorIdStrings.RunAs32NotSupported;595                var errorRecord = new ErrorRecord(596                    new PSNotSupportedException(message),597                    "RunAs32NotSupported",598                    ErrorCategory.InvalidOperation,599                    targetObject: null);600 601                ThrowTerminatingError(errorRecord);602            }603 604            if (WorkingDirectory != null && !InvokeProvider.Item.IsContainer(WorkingDirectory))605            {606                string message = StringUtil.Format(RemotingErrorIdStrings.StartJobWorkingDirectoryNotFound, WorkingDirectory);607                var errorRecord = new ErrorRecord(608                    new DirectoryNotFoundException(message),609                    "DirectoryNotFoundException",610                    ErrorCategory.InvalidOperation,611                    targetObject: null);612 613                ThrowTerminatingError(errorRecord);614            }615 616            if (WorkingDirectory == null)617            {618                try619                {620                    WorkingDirectory = SessionState.Internal.CurrentLocation.Path;621                }622                catch (PSInvalidOperationException)623                {624                }625            }626 627            CommandDiscovery.AutoloadModulesWithJobSourceAdapters(this.Context, this.CommandOrigin);628 629            if (ParameterSetName == DefinitionNameParameterSet)630            {631                return;632            }633 634            // since jobs no more depend on WinRM635            // we will have to skip the check for the same636            SkipWinRMCheck = true;637 638            base.BeginProcessing();639        }640 641        /// <summary>642        /// Create a throttle operation using NewProcessConnectionInfo643        /// ie., Out-Of-Process runspace.644        /// </summary>645        protected override void CreateHelpersForSpecifiedComputerNames()646        {647            // If we're in ConstrainedLanguage mode and the system is in lockdown mode,648            // ensure that they haven't specified a ScriptBlock or InitScript - as649            // we can't protect that boundary.650            if ((Context.LanguageMode == PSLanguageMode.ConstrainedLanguage) &&651                (SystemPolicy.GetSystemLockdownPolicy() != SystemEnforcementMode.Enforce) &&652                ((ScriptBlock != null) || (InitializationScript != null)))653            {654                ThrowTerminatingError(655                    new ErrorRecord(656                        new PSNotSupportedException(RemotingErrorIdStrings.CannotStartJobInconsistentLanguageMode),657                            "CannotStartJobInconsistentLanguageMode",658                            ErrorCategory.PermissionDenied,659                            Context.LanguageMode));660            }661 662            NewProcessConnectionInfo connectionInfo = new NewProcessConnectionInfo(this.Credential);663            connectionInfo.InitializationScript = _initScript;664            connectionInfo.AuthenticationMechanism = this.Authentication;665            connectionInfo.PSVersion = this.PSVersion;666            connectionInfo.WorkingDirectory = this.WorkingDirectory;667 668            RemoteRunspace remoteRunspace = (RemoteRunspace)RunspaceFactory.CreateRunspace(connectionInfo, this.Host,669                        Utils.GetTypeTableFromExecutionContextTLS());670 671            remoteRunspace.Events.ReceivedEvents.PSEventReceived += OnRunspacePSEventReceived;672 673            Pipeline pipeline = CreatePipeline(remoteRunspace);674 675            IThrottleOperation operation =676                new ExecutionCmdletHelperComputerName(remoteRunspace, pipeline);677 678            Operations.Add(operation);679        }680        /// <summary>681        /// The expression will be executed in the remote computer if a682        /// remote runspace parameter or computer name is specified. If683        /// none other than command parameter is specified, then it684        /// just executes the command locally without creating a new685        /// remote runspace object.686        /// </summary>687        protected override void ProcessRecord()688        {689            if (ParameterSetName == DefinitionNameParameterSet)690            {691                // Get the Job2 object from the Job Manager for this definition name and start the job.692                string resolvedPath = null;693                if (!string.IsNullOrEmpty(_definitionPath))694                {695                    ProviderInfo provider = null;696                    System.Collections.ObjectModel.Collection<string> paths =697                        this.Context.SessionState.Path.GetResolvedProviderPathFromPSPath(_definitionPath, out provider);698 699                    // Only file system paths are allowed.700                    if (!provider.NameEquals(this.Context.ProviderNames.FileSystem))701                    {702                        string message = StringUtil.Format(RemotingErrorIdStrings.StartJobDefinitionPathInvalidNotFSProvider,703                            _definitionName,704                            _definitionPath,705                            provider.FullName);706                        WriteError(new ErrorRecord(new RuntimeException(message), "StartJobFromDefinitionNamePathInvalidNotFileSystemProvider",707                            ErrorCategory.InvalidArgument, null));708 709                        return;710                    }711 712                    // Only a single file path is allowed.713                    if (paths.Count != 1)714                    {715                        string message = StringUtil.Format(RemotingErrorIdStrings.StartJobDefinitionPathInvalidNotSingle,716                            _definitionName,717                            _definitionPath);718                        WriteError(new ErrorRecord(new RuntimeException(message), "StartJobFromDefinitionNamePathInvalidNotSingle",719                            ErrorCategory.InvalidArgument, null));720 721                        return;722                    }723 724                    resolvedPath = paths[0];725                }726 727                List<Job2> jobs = JobManager.GetJobToStart(_definitionName, resolvedPath, _definitionType, this, false);728 729                if (jobs.Count == 0)730                {731                    string message = (_definitionType != null) ?732                        StringUtil.Format(RemotingErrorIdStrings.StartJobDefinitionNotFound2, _definitionType, _definitionName) :733                        StringUtil.Format(RemotingErrorIdStrings.StartJobDefinitionNotFound1, _definitionName);734 735                    WriteError(new ErrorRecord(new RuntimeException(message), "StartJobFromDefinitionNameNotFound",736                        ErrorCategory.ObjectNotFound, null));737 738                    return;739                }740 741                if (jobs.Count > 1)742                {743                    string message = StringUtil.Format(RemotingErrorIdStrings.StartJobManyDefNameMatches, _definitionName);744                    WriteError(new ErrorRecord(new RuntimeException(message), "StartJobFromDefinitionNameMoreThanOneMatch",745                        ErrorCategory.InvalidResult, null));746 747                    return;748                }749 750                // Start job.751                Job2 job = jobs[0];752                job.StartJob();753 754                // Write job object to host.755                WriteObject(job);756 757                return;758            }759 760            if (_firstProcessRecord)761            {762                _firstProcessRecord = false;763 764                PSRemotingJob job = new PSRemotingJob(ResolvedComputerNames, Operations,765                        ScriptBlock.ToString(), ThrottleLimit, _name);766 767                job.PSJobTypeName = s_startJobType;768 769                this.JobRepository.Add(job);770                WriteObject(job);771            }772 773            // inject input774            if (InputObject != AutomationNull.Value)775            {776                foreach (IThrottleOperation operation in Operations)777                {778                    ExecutionCmdletHelper helper = (ExecutionCmdletHelper)operation;779                    helper.Pipeline.Input.Write(InputObject);780                }781            }782        }783 784        private bool _firstProcessRecord = true;785 786        /// <summary>787        /// InvokeAsync would have been called in ProcessRecord. Wait here788        /// for all the results to become available.789        /// </summary>790        protected override void EndProcessing()791        {792            // close the input stream on all the pipelines793            CloseAllInputStreams();794        }795 796        #endregion Overrides797 798        #region IDisposable Overrides799 800        /// <summary>801        /// Dispose the cmdlet.802        /// </summary>803        public void Dispose()804        {805            Dispose(true);806            GC.SuppressFinalize(this);807        }808 809        /// <summary>810        /// Internal dispose method which does the actual disposing.811        /// </summary>812        /// <param name="disposing">Whether called from dispose or finalize.</param>813        private void Dispose(bool disposing)814        {815            if (disposing)816            {817                CloseAllInputStreams();818            }819        }820 821        #endregion IDisposable Overrides822    }823}824