Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
ResumeJob.cs301 linesDownload Raw Back to commands
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System;5using System.Collections.Generic;6using System.ComponentModel;7using System.Diagnostics.CodeAnalysis;8using System.Linq;9using System.Management.Automation;10using System.Management.Automation.Remoting;11using System.Threading;12 13namespace Microsoft.PowerShell.Commands14{15    /// <summary>16    /// This cmdlet resumes the jobs that are Job2. Errors are added for each Job that is not Job2.17    /// </summary>18#if !CORECLR19    [SuppressMessage("Microsoft.PowerShell", "PS1012:CallShouldProcessOnlyIfDeclaringSupport")]20    [Cmdlet(VerbsLifecycle.Resume, "Job", SupportsShouldProcess = true, DefaultParameterSetName = JobCmdletBase.SessionIdParameterSet,21        HelpUri = "https://go.microsoft.com/fwlink/?LinkID=210611")]22#endif23    [OutputType(typeof(Job))]24    public class ResumeJobCommand : JobCmdletBase, IDisposable25    {26        #region Parameters27        /// <summary>28        /// Specifies the Jobs objects which need to be29        /// suspended.30        /// </summary>31        [Parameter(Mandatory = true,32                   Position = 0,33                   ValueFromPipeline = true,34                   ValueFromPipelineByPropertyName = true,35                   ParameterSetName = JobParameterSet)]36        [ValidateNotNullOrEmpty]37        [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]38        public Job[] Job39        {40            get41            {42                return _jobs;43            }44 45            set46            {47                _jobs = value;48            }49        }50 51        private Job[] _jobs;52 53        /// <summary>54        /// </summary>55        public override string[] Command56        {57            get58            {59                return null;60            }61        }62 63        /// <summary>64        /// Specifies whether to delay returning from the cmdlet until all jobs reach a running state.65        /// This could take significant time due to workflow throttling.66        /// </summary>67        [Parameter(ParameterSetName = ParameterAttribute.AllParameterSets)]68        public SwitchParameter Wait { get; set; }69 70        #endregion Parameters71 72        #region Overrides73 74        /// <summary>75        /// Resume the Job.76        /// </summary>77        protected override void ProcessRecord()78        {79            // List of jobs to resume80            List<Job> jobsToResume = null;81 82            switch (ParameterSetName)83            {84                case NameParameterSet:85                    {86                        jobsToResume = FindJobsMatchingByName(true, false, true, false);87                    }88 89                    break;90 91                case InstanceIdParameterSet:92                    {93                        jobsToResume = FindJobsMatchingByInstanceId(true, false, true, false);94                    }95 96                    break;97 98                case SessionIdParameterSet:99                    {100                        jobsToResume = FindJobsMatchingBySessionId(true, false, true, false);101                    }102 103                    break;104 105                case StateParameterSet:106                    {107                        jobsToResume = FindJobsMatchingByState(false);108                    }109 110                    break;111 112                case FilterParameterSet:113                    {114                        jobsToResume = FindJobsMatchingByFilter(false);115                    }116 117                    break;118 119                default:120                    {121                        jobsToResume = CopyJobsToList(_jobs, false, false);122                    }123 124                    break;125            }126 127            _allJobsToResume.AddRange(jobsToResume);128 129            // Blue: 151804 When resuming a single suspended workflow job, Resume-job cmdlet doesn't wait for the job to be in running state130            // Setting Wait to true so that this cmdlet will wait for the running job state.131            if (_allJobsToResume.Count == 1)132                Wait = true;133 134            foreach (Job job in jobsToResume)135            {136                var job2 = job as Job2;137 138                // If the job is not Job2, the resume operation is not supported.139                if (job2 == null)140                {141                    WriteError(new ErrorRecord(PSTraceSource.NewNotSupportedException(RemotingErrorIdStrings.JobResumeNotSupported, job.Id), "Job2OperationNotSupportedOnJob", ErrorCategory.InvalidType, (object)job));142                    continue;143                }144 145                string targetString = PSRemotingErrorInvariants.FormatResourceString(RemotingErrorIdStrings.RemovePSJobWhatIfTarget, job.Command, job.Id);146                if (ShouldProcess(targetString, VerbsLifecycle.Resume))147                {148                    _cleanUpActions.Add(job2, HandleResumeJobCompleted);149                    job2.ResumeJobCompleted += HandleResumeJobCompleted;150 151                    lock (_syncObject)152                    {153                        if (!_pendingJobs.Contains(job2.InstanceId))154                        {155                            _pendingJobs.Add(job2.InstanceId);156                        }157                    }158 159                    job2.ResumeJobAsync();160                }161            }162        }163 164        private bool _warnInvalidState = false;165        private readonly HashSet<Guid> _pendingJobs = new HashSet<Guid>();166        private readonly ManualResetEvent _waitForJobs = new ManualResetEvent(false);167        private readonly Dictionary<Job2, EventHandler<AsyncCompletedEventArgs>> _cleanUpActions =168            new Dictionary<Job2, EventHandler<AsyncCompletedEventArgs>>();169        private readonly List<ErrorRecord> _errorsToWrite = new List<ErrorRecord>();170        private readonly List<Job> _allJobsToResume = new List<Job>();171        private readonly object _syncObject = new object();172        private bool _needToCheckForWaitingJobs;173 174        private void HandleResumeJobCompleted(object sender, AsyncCompletedEventArgs eventArgs)175        {176            Job job = sender as Job;177 178            if (eventArgs.Error != null && eventArgs.Error is InvalidJobStateException)179            {180                _warnInvalidState = true;181            }182 183            var parentJob = job as ContainerParentJob;184            if (parentJob != null && parentJob.ExecutionError.Count > 0)185            {186                foreach (187                    var e in188                        parentJob.ExecutionError.Where(static e => e.FullyQualifiedErrorId == "ContainerParentJobResumeAsyncError")189                    )190                {191                    if (e.Exception is InvalidJobStateException)192                    {193                        // if any errors were invalid job state exceptions, warn the user.194                        // This is to support Get-Job | Resume-Job scenarios when many jobs195                        // are Completed, etc.196                        _warnInvalidState = true;197                    }198                    else199                    {200                        _errorsToWrite.Add(e);201                    }202                }203 204                parentJob.ExecutionError.Clear();205            }206 207            bool releaseWait = false;208            lock (_syncObject)209            {210                if (_pendingJobs.Contains(job.InstanceId))211                {212                    _pendingJobs.Remove(job.InstanceId);213                }214 215                if (_needToCheckForWaitingJobs && _pendingJobs.Count == 0)216                    releaseWait = true;217            }218            // end processing has been called219            // set waithandle if this is the last one220            if (releaseWait)221                _waitForJobs.Set();222        }223 224        /// <summary>225        /// End Processing.226        /// </summary>227        protected override void EndProcessing()228        {229            bool jobsPending = false;230            lock (_syncObject)231            {232                _needToCheckForWaitingJobs = true;233                if (_pendingJobs.Count > 0)234                {235                    jobsPending = true;236                }237            }238 239            if (Wait && jobsPending)240            {241                _waitForJobs.WaitOne();242            }243 244            if (_warnInvalidState)245            {246                WriteWarning(RemotingErrorIdStrings.ResumeJobInvalidJobState);247            }248 249            foreach (var e in _errorsToWrite)250            {251                WriteError(e);252            }253 254            foreach (var j in _allJobsToResume)255            {256                WriteObject(j);257            }258 259            base.EndProcessing();260        }261 262        /// <summary>263        /// </summary>264        protected override void StopProcessing()265        {266            _waitForJobs.Set();267        }268 269        #endregion Overrides270 271        #region Dispose272 273        /// <summary>274        /// </summary>275        public void Dispose()276        {277            Dispose(true);278            GC.SuppressFinalize(this);279        }280 281        /// <summary>282        /// </summary>283        /// <param name="disposing"></param>284        protected void Dispose(bool disposing)285        {286            if (!disposing)287            {288                return;289            }290 291            foreach (var pair in _cleanUpActions)292            {293                pair.Key.ResumeJobCompleted -= pair.Value;294            }295 296            _waitForJobs.Dispose();297        }298        #endregion Dispose299    }300}301