MegaBites-AI/Windows-powershell
0372
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 stops the asynchronously invoked remote operations.17 /// </summary>18 [Cmdlet(VerbsLifecycle.Stop, "Job", SupportsShouldProcess = true, DefaultParameterSetName = JobCmdletBase.SessionIdParameterSet,19 HelpUri = "https://go.microsoft.com/fwlink/?LinkID=2096795")]20 [OutputType(typeof(Job))]21 public class StopJobCommand : JobCmdletBase, IDisposable22 {23 #region Parameters24 /// <summary>25 /// Specifies the Jobs objects which need to be26 /// removed.27 /// </summary>28 [Parameter(Mandatory = true,29 Position = 0,30 ValueFromPipeline = true,31 ValueFromPipelineByPropertyName = true,32 ParameterSetName = RemoveJobCommand.JobParameterSet)]33 [ValidateNotNullOrEmpty]34 [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]35 public Job[] Job36 {37 get38 {39 return _jobs;40 }41 42 set43 {44 _jobs = value;45 }46 }47 48 private Job[] _jobs;49 50 /// <summary>51 /// Pass the Job object through the pipeline.52 /// </summary>53 [Parameter]54 public SwitchParameter PassThru55 {56 get57 {58 return _passThru;59 }60 61 set62 {63 _passThru = value;64 }65 }66 67 private bool _passThru;68 69 /// <summary>70 /// </summary>71 public override string[] Command72 {73 get74 {75 return null;76 }77 }78 79 #endregion Parameters80 81 #region Overrides82 83 /// <summary>84 /// Stop the Job.85 /// </summary>86 protected override void ProcessRecord()87 {88 // List of jobs to stop89 List<Job> jobsToStop = null;90 91 switch (ParameterSetName)92 {93 case NameParameterSet:94 {95 jobsToStop = FindJobsMatchingByName(true, false, true, false);96 }97 98 break;99 100 case InstanceIdParameterSet:101 {102 jobsToStop = FindJobsMatchingByInstanceId(true, false, true, false);103 }104 105 break;106 107 case SessionIdParameterSet:108 {109 jobsToStop = FindJobsMatchingBySessionId(true, false, true, false);110 }111 112 break;113 114 case StateParameterSet:115 {116 jobsToStop = FindJobsMatchingByState(false);117 }118 119 break;120 121 case FilterParameterSet:122 {123 jobsToStop = FindJobsMatchingByFilter(false);124 }125 126 break;127 128 default:129 {130 jobsToStop = CopyJobsToList(_jobs, false, false);131 }132 133 break;134 }135 136 _allJobsToStop.AddRange(jobsToStop);137 138 foreach (Job job in jobsToStop)139 {140 if (this.Stopping)141 {142 return;143 }144 145 if (job.IsFinishedState(job.JobStateInfo.State))146 {147 continue;148 }149 150 string targetString =151 PSRemotingErrorInvariants.FormatResourceString(RemotingErrorIdStrings.RemovePSJobWhatIfTarget,152 job.Command, job.Id);153 if (ShouldProcess(targetString, VerbsLifecycle.Stop))154 {155 Job2 job2 = job as Job2;156 // if it is a Job2, then async is supported157 // stop the job asynchronously158 if (job2 != null)159 {160 _cleanUpActions.Add(job2, HandleStopJobCompleted);161 job2.StopJobCompleted += HandleStopJobCompleted;162 163 lock (_syncObject)164 {165 if (!job2.IsFinishedState(job2.JobStateInfo.State) &&166 !_pendingJobs.Contains(job2.InstanceId))167 {168 _pendingJobs.Add(job2.InstanceId);169 }170 }171 172 job2.StopJobAsync();173 }174 else175 {176 job.StopJob();177 }178 }179 }180 }181 182 /// <summary>183 /// Wait for all the stop jobs to be completed.184 /// </summary>185 protected override void EndProcessing()186 {187 bool haveToWait = false;188 lock (_syncObject)189 {190 _needToCheckForWaitingJobs = true;191 if (_pendingJobs.Count > 0)192 haveToWait = true;193 }194 195 if (haveToWait)196 _waitForJobs.WaitOne();197 198 foreach (var e in _errorsToWrite) WriteError(e);199 if (_passThru)200 {201 foreach (var job in _allJobsToStop) WriteObject(job);202 }203 }204 205 /// <summary>206 /// </summary>207 protected override void StopProcessing()208 {209 _waitForJobs.Set();210 }211 212 #endregion Overrides213 214 #region Private Methods215 216 private void HandleStopJobCompleted(object sender, AsyncCompletedEventArgs eventArgs)217 {218 Job job = sender as Job;219 220 if (eventArgs.Error != null)221 {222 _errorsToWrite.Add(new ErrorRecord(eventArgs.Error, "StopJobError", ErrorCategory.ReadError, job));223 }224 225 var parentJob = job as ContainerParentJob;226 if (parentJob != null && parentJob.ExecutionError.Count > 0)227 {228 foreach (229 var e in230 parentJob.ExecutionError.Where(231 e => e.FullyQualifiedErrorId == "ContainerParentJobStopAsyncError"))232 {233 _errorsToWrite.Add(e);234 }235 }236 237 bool releaseWait = false;238 lock (_syncObject)239 {240 if (_pendingJobs.Contains(job.InstanceId))241 {242 _pendingJobs.Remove(job.InstanceId);243 }244 245 if (_needToCheckForWaitingJobs && _pendingJobs.Count == 0)246 releaseWait = true;247 }248 // end processing has been called249 // set waithandle if this is the last one250 if (releaseWait)251 _waitForJobs.Set();252 }253 254 #endregion Private Methods255 256 #region Private Members257 258 private readonly HashSet<Guid> _pendingJobs = new HashSet<Guid>();259 private readonly ManualResetEvent _waitForJobs = new ManualResetEvent(false);260 261 private readonly Dictionary<Job2, EventHandler<AsyncCompletedEventArgs>> _cleanUpActions =262 new Dictionary<Job2, EventHandler<AsyncCompletedEventArgs>>();263 264 private readonly List<Job> _allJobsToStop = new List<Job>();265 private readonly List<ErrorRecord> _errorsToWrite = new List<ErrorRecord>();266 267 private readonly object _syncObject = new object();268 private bool _needToCheckForWaitingJobs;269 270 #endregion Private Members271 272 #region Dispose273 274 /// <summary>275 /// </summary>276 public void Dispose()277 {278 Dispose(true);279 GC.SuppressFinalize(this);280 }281 282 /// <summary>283 /// </summary>284 /// <param name="disposing"></param>285 protected void Dispose(bool disposing)286 {287 if (!disposing)288 {289 return;290 }291 292 foreach (var pair in _cleanUpActions)293 {294 pair.Key.StopJobCompleted -= pair.Value;295 }296 297 _waitForJobs.Dispose();298 }299 #endregion Dispose300 }301}302 