Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
Process.cs3016 linesDownload Raw Back to management
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.Collections.Specialized;9using System.ComponentModel; // Win32Exception10using System.Diagnostics; // Process class11using System.Diagnostics.CodeAnalysis;12using System.IO;13using System.Management.Automation;14using System.Management.Automation.Internal;15using System.Management.Automation.Language;16using System.Net;17using System.Runtime.InteropServices;18using System.Runtime.Serialization;19using System.Security.Principal;20using System.Text;21using System.Threading;22using Microsoft.Management.Infrastructure;23using Microsoft.PowerShell.Commands.Internal;24using Microsoft.Win32.SafeHandles;25 26namespace Microsoft.PowerShell.Commands27{28    #region ProcessBaseCommand29    /// <summary>30    /// This class implements the base for process commands.31    /// </summary>32    public abstract class ProcessBaseCommand : Cmdlet33    {34        #region Parameters35        /// <summary>36        /// The various process selection modes.37        /// </summary>38        internal enum MatchMode39        {40            /// <summary>41            /// Select all processes.42            /// </summary>43            All,44            /// <summary>45            /// Select processes matching the supplied names.46            /// </summary>47            ByName,48            /// <summary>49            /// Select the processes matching the id.50            /// </summary>51            ById,52            /// <summary>53            /// Select the processes specified as input.54            /// </summary>55            ByInput56        }57        /// <summary>58        /// The current process selection mode.59        /// </summary>60        internal MatchMode myMode = MatchMode.All;61 62        /// <remarks>63        /// The Name parameter is declared in subclasses,64        /// since it is optional for GetProcess and mandatory for StopProcess.65        /// </remarks>66        internal string[] processNames = null;67 68        // The Id parameter is declared in subclasses,69        // since it is positional for StopProcess but not for GetProcess.70        internal int[] processIds = null;71 72        /// <summary>73        /// If the input is a stream of [collections of]74        /// Process objects, we bypass the Name and75        /// Id parameters and read the Process objects76        /// directly.  This allows us to deal with processes which77        /// have wildcard characters in their name.78        /// </summary>79        /// <value>Process objects</value>80        [Parameter(81            ParameterSetName = "InputObject",82            Mandatory = true,83            ValueFromPipeline = true)]84        public virtual Process[] InputObject85        {86            get87            {88                return _input;89            }90 91            set92            {93                myMode = MatchMode.ByInput;94                _input = value;95            }96        }97 98        private Process[] _input = null;99        #endregion Parameters100 101        #region Internal102 103        // We use a Dictionary to optimize the check whether the object104        // is already in the list.105        private List<Process> _matchingProcesses = new();106        private readonly Dictionary<int, Process> _keys = new();107 108        /// <summary>109        /// Retrieve the list of all processes matching the Name, Id110        /// and InputObject parameters, sorted by Id.111        /// </summary>112        /// <returns></returns>113        internal List<Process> MatchingProcesses()114        {115            _matchingProcesses.Clear();116            switch (myMode)117            {118                case MatchMode.ById:119                    RetrieveMatchingProcessesById();120                    break;121 122                case MatchMode.ByInput:123                    RetrieveProcessesByInput();124                    break;125                default:126                    // Default is "Name":127                    RetrieveMatchingProcessesByProcessName();128                    break;129            }130            // 2004/12/16 Note that the processes will be sorted131            //  before being stopped.  PM confirms that this is fine.132            _matchingProcesses.Sort(ProcessComparison);133            return _matchingProcesses;134        }135 136        /// <summary>137        /// Sort function to sort by Name first, then Id.138        /// </summary>139        /// <param name="x">First Process object.</param>140        /// <param name="y">Second Process object.</param>141        /// <returns>142        /// As string.Compare: returns less than zero if x less than y,143        /// greater than 0 if x greater than y, 0 if x == y.144        /// </returns>145        private static int ProcessComparison(Process x, Process y)146        {147            int diff = string.Compare(148                SafeGetProcessName(x),149                SafeGetProcessName(y),150                StringComparison.OrdinalIgnoreCase);151            if (diff != 0)152                return diff;153            return SafeGetProcessId(x) - SafeGetProcessId(y);154        }155 156        /// <summary>157        /// Retrieves the list of all processes matching the Name158        /// parameter.159        /// Generates a non-terminating error for each specified160        /// process name which is not found even though it contains161        /// no wildcards.162        /// </summary>163        /// <returns></returns>164        private void RetrieveMatchingProcessesByProcessName()165        {166            if (processNames == null)167            {168                _matchingProcesses = new List<Process>(AllProcesses);169                return;170            }171 172            foreach (string pattern in processNames)173            {174                WildcardPattern wildcard =175                    WildcardPattern.Get(pattern, WildcardOptions.IgnoreCase);176                bool found = false;177                foreach (Process process in AllProcesses)178                {179                    if (!wildcard.IsMatch(SafeGetProcessName(process)))180                        continue;181                    found = true;182                    AddIdempotent(process);183                }184 185                if (!found &&186                    !WildcardPattern.ContainsWildcardCharacters(pattern))187                {188                    string errorText = ProcessResources.NoProcessFoundForGivenName;189                    string errorName = nameof(ProcessResources.NoProcessFoundForGivenName);190 191                    if (int.TryParse(pattern, out int x) && x >= 0)192                    {193                        errorText = ProcessResources.RecommendIdTagForGivenName;194                        errorName = nameof(ProcessResources.RecommendIdTagForGivenName);195                    }196 197                    WriteNonTerminatingError(198                        processName: pattern,199                        processId: 0,200                        targetObject: pattern,201                        innerException: null,202                        resourceId: errorText,203                        errorId: errorName,204                        category: ErrorCategory.ObjectNotFound);205                }206            }207        }208 209        /// <summary>210        /// Retrieves the list of all processes matching the Id211        /// parameter.212        /// Generates a non-terminating error for each specified213        /// process ID which is not found.214        /// </summary>215        /// <returns></returns>216        private void RetrieveMatchingProcessesById()217        {218            if (processIds == null)219            {220                Diagnostics.Assert(false, "null processIds");221                throw PSTraceSource.NewInvalidOperationException();222            }223 224            foreach (int processId in processIds)225            {226                Process process;227                try228                {229                    process = Process.GetProcessById(processId);230                    AddIdempotent(process);231                }232                catch (ArgumentException)233                {234                    WriteNonTerminatingError(235                        string.Empty,236                        processId,237                        processId,238                        null,239                        ProcessResources.NoProcessFoundForGivenId,240                        "NoProcessFoundForGivenId",241                        ErrorCategory.ObjectNotFound);242                    continue;243                }244            }245        }246 247        /// <summary>248        /// Retrieves the list of all processes matching the InputObject249        /// parameter.250        /// </summary>251        /// <returns></returns>252        private void RetrieveProcessesByInput()253        {254            if (InputObject == null)255            {256                Diagnostics.Assert(false, "null InputObject");257                throw PSTraceSource.NewInvalidOperationException();258            }259 260            foreach (Process process in InputObject)261            {262                SafeRefresh(process);263                AddIdempotent(process);264            }265        }266 267        /// <summary>268        /// Gets an array of all processes.269        /// </summary>270        /// <value>An array of <see cref="Process"/> components that represents all the process resources.</value>271        /// <exception cref="System.Security.SecurityException">272        /// MSDN does not document the list of exceptions,273        /// but it is reasonable to expect that SecurityException is274        /// among them.  Errors here will terminate the cmdlet.275        /// </exception>276        internal Process[] AllProcesses => _allProcesses ??= Process.GetProcesses();277 278        private Process[] _allProcesses;279 280        /// <summary>281        /// Add <paramref name="process"/> to <see cref="_matchingProcesses"/>,282        /// but only if it is not already on  <see cref="_matchingProcesses"/>.283        /// We use a Dictionary to optimize the check whether the object284        /// is already in the list.285        /// </summary>286        /// <param name="process">Process to add to list.</param>287        private void AddIdempotent(288            Process process)289        {290            int hashCode = SafeGetProcessName(process).GetHashCode()291                ^ SafeGetProcessId(process); // XOR292            if (!_keys.ContainsKey(hashCode))293            {294                _keys.Add(hashCode, process);295                _matchingProcesses.Add(process);296            }297        }298 299        /// <summary>300        /// Writes a non-terminating error.301        /// </summary>302        /// <param name="process"></param>303        /// <param name="innerException"></param>304        /// <param name="resourceId"></param>305        /// <param name="errorId"></param>306        /// <param name="category"></param>307        internal void WriteNonTerminatingError(308            Process process,309            Exception innerException,310            string resourceId, string errorId,311            ErrorCategory category)312        {313            WriteNonTerminatingError(314                SafeGetProcessName(process),315                SafeGetProcessId(process),316                process,317                innerException,318                resourceId,319                errorId,320                category);321        }322 323        /// <summary>324        /// Writes a non-terminating error.325        /// </summary>326        /// <param name="processName"></param>327        /// <param name="processId"></param>328        /// <param name="targetObject"></param>329        /// <param name="innerException"></param>330        /// <param name="resourceId"></param>331        /// <param name="errorId"></param>332        /// <param name="category"></param>333        internal void WriteNonTerminatingError(334            string processName,335            int processId,336            object targetObject,337            Exception innerException,338            string resourceId,339            string errorId,340            ErrorCategory category)341        {342            string message = StringUtil.Format(resourceId,343                processName,344                processId,345                (innerException == null) ? string.Empty : innerException.Message);346            ProcessCommandException exception =347                new(message, innerException);348            exception.ProcessName = processName;349 350            WriteError(new ErrorRecord(351                exception, errorId, category, targetObject));352        }353 354        // The Name property is not always available, even for355        // live processes (such as the Idle process).356        internal static string SafeGetProcessName(Process process)357        {358            try359            {360                return process.ProcessName;361            }362            catch (Win32Exception)363            {364                return string.Empty;365            }366            catch (InvalidOperationException)367            {368                return string.Empty;369            }370        }371 372        // 2004/12/17-JonN I saw this fail once too, so we'll play it safe373        internal static int SafeGetProcessId(Process process)374        {375            try376            {377                return process.Id;378            }379            catch (Win32Exception)380            {381                return int.MinValue;382            }383            catch (InvalidOperationException)384            {385                return int.MinValue;386            }387        }388 389        internal static void SafeRefresh(Process process)390        {391            try392            {393                process.Refresh();394            }395            catch (Win32Exception)396            {397            }398            catch (InvalidOperationException)399            {400            }401        }402 403        /// <summary>404        /// TryHasExited is a helper function used to detect if the process has aready exited or not.405        /// </summary>406        /// <param name="process">407        /// Process whose exit status has to be checked.408        /// </param>409        /// <returns>Tre if the process has exited or else returns false.</returns>410        internal static bool TryHasExited(Process process)411        {412            bool hasExited = true;413 414            try415            {416                hasExited = process.HasExited;417            }418            catch (Win32Exception)419            {420                hasExited = false;421            }422            catch (InvalidOperationException)423            {424                hasExited = false;425            }426 427            return hasExited;428        }429 430        #endregion Internal431    }432    #endregion ProcessBaseCommand433 434    #region GetProcessCommand435    /// <summary>436    /// This class implements the get-process command.437    /// </summary>438    [Cmdlet(VerbsCommon.Get, "Process", DefaultParameterSetName = NameParameterSet,439        HelpUri = "https://go.microsoft.com/fwlink/?LinkID=2096814", RemotingCapability = RemotingCapability.SupportedByCommand)]440    [OutputType(typeof(ProcessModule), typeof(FileVersionInfo), typeof(Process))]441    public sealed class GetProcessCommand : ProcessBaseCommand442    {443        #region ParameterSetStrings444 445        private const string NameParameterSet = "Name";446        private const string IdParameterSet = "Id";447        private const string InputObjectParameterSet = "InputObject";448        private const string NameWithUserNameParameterSet = "NameWithUserName";449        private const string IdWithUserNameParameterSet = "IdWithUserName";450        private const string InputObjectWithUserNameParameterSet = "InputObjectWithUserName";451 452        #endregion ParameterSetStrings453 454        #region Parameters455 456        /// <summary>457        /// Has the list of process names on which to this command will work.458        /// </summary>459        [Parameter(Position = 0, ParameterSetName = NameParameterSet, ValueFromPipelineByPropertyName = true)]460        [Parameter(Position = 0, ParameterSetName = NameWithUserNameParameterSet, ValueFromPipelineByPropertyName = true)]461        [Alias("ProcessName")]462        [ValidateNotNullOrEmpty]463        public string[] Name464        {465            get466            {467                return processNames;468            }469 470            set471            {472                myMode = MatchMode.ByName;473                processNames = value;474            }475        }476 477        /// <summary>478        /// Gets/sets an array of process IDs.479        /// </summary>480        [Parameter(ParameterSetName = IdParameterSet, Mandatory = true, ValueFromPipelineByPropertyName = true)]481        [Parameter(ParameterSetName = IdWithUserNameParameterSet, Mandatory = true, ValueFromPipelineByPropertyName = true)]482        [Alias("PID")]483        public int[] Id484        {485            get486            {487                return processIds;488            }489 490            set491            {492                myMode = MatchMode.ById;493                processIds = value;494            }495        }496 497        /// <summary>498        /// Input is a stream of [collections of] Process objects.499        /// </summary>500        [Parameter(ParameterSetName = InputObjectParameterSet, Mandatory = true, ValueFromPipeline = true)]501        [Parameter(ParameterSetName = InputObjectWithUserNameParameterSet, Mandatory = true, ValueFromPipeline = true)]502        public override Process[] InputObject503        {504            get505            {506                return base.InputObject;507            }508 509            set510            {511                base.InputObject = value;512            }513        }514 515        /// <summary>516        /// Include the UserName.517        /// </summary>518        [Parameter(ParameterSetName = NameWithUserNameParameterSet, Mandatory = true)]519        [Parameter(ParameterSetName = IdWithUserNameParameterSet, Mandatory = true)]520        [Parameter(ParameterSetName = InputObjectWithUserNameParameterSet, Mandatory = true)]521        public SwitchParameter IncludeUserName { get; set; }522 523        /// <summary>524        /// To display the modules of a process.525        /// </summary>526        [Parameter(ParameterSetName = NameParameterSet)]527        [Parameter(ParameterSetName = IdParameterSet)]528        [Parameter(ParameterSetName = InputObjectParameterSet)]529        [ValidateNotNull]530        public SwitchParameter Module { get; set; }531 532        /// <summary>533        /// To display the fileversioninfo of the main module of a process.534        /// </summary>535        [Parameter(ParameterSetName = NameParameterSet)]536        [Parameter(ParameterSetName = IdParameterSet)]537        [Parameter(ParameterSetName = InputObjectParameterSet)]538        [Alias("FV", "FVI")]539        [ValidateNotNull]540        public SwitchParameter FileVersionInfo { get; set; }541 542        #endregion Parameters543 544        #region Overrides545 546        /// <summary>547        /// Write the process objects.548        /// </summary>549        protected override void ProcessRecord()550        {551            foreach (Process process in MatchingProcesses())552            {553                if (Module.IsPresent && FileVersionInfo.IsPresent)554                {555                    ProcessModule tempmodule = null;556                    try557                    {558                        ProcessModuleCollection modules = process.Modules;559                        foreach (ProcessModule pmodule in modules)560                        {561                            // Assigning to tempmodule to rethrow for exceptions on 64 bit machines562                            tempmodule = pmodule;563                            WriteObject(pmodule.FileVersionInfo, true);564                        }565                    }566                    catch (InvalidOperationException exception)567                    {568                        WriteNonTerminatingError(process, exception, ProcessResources.CouldNotEnumerateModuleFileVer, "CouldNotEnumerateModuleFileVer", ErrorCategory.PermissionDenied);569                    }570                    catch (ArgumentException exception)571                    {572                        WriteNonTerminatingError(process, exception, ProcessResources.CouldNotEnumerateModuleFileVer, "CouldNotEnumerateModuleFileVer", ErrorCategory.PermissionDenied);573                    }574                    catch (Win32Exception exception)575                    {576                        try577                        {578                            if (exception.HResult == 299)579                            {580                                WriteObject(tempmodule.FileVersionInfo, true);581                            }582                            else583                            {584                                WriteNonTerminatingError(process, exception, ProcessResources.CouldNotEnumerateModuleFileVer, "CouldNotEnumerateModuleFileVer", ErrorCategory.PermissionDenied);585                            }586                        }587                        catch (Win32Exception ex)588                        {589                            WriteNonTerminatingError(process, ex, ProcessResources.CouldNotEnumerateModuleFileVer, "CouldNotEnumerateModuleFileVer", ErrorCategory.PermissionDenied);590                        }591                    }592                    catch (Exception exception)593                    {594                        WriteNonTerminatingError(process, exception, ProcessResources.CouldNotEnumerateModuleFileVer, "CouldNotEnumerateModuleFileVer", ErrorCategory.PermissionDenied);595                    }596                }597                else if (Module.IsPresent)598                {599                    try600                    {601                        WriteObject(process.Modules, true);602                    }603                    catch (Win32Exception exception)604                    {605                        try606                        {607                            if (exception.HResult == 299)608                            {609                                WriteObject(process.Modules, true);610                            }611                            else612                            {613                                WriteNonTerminatingError(process, exception, ProcessResources.CouldNotEnumerateModules, "CouldNotEnumerateModules", ErrorCategory.PermissionDenied);614                            }615                        }616                        catch (Win32Exception ex)617                        {618                            WriteNonTerminatingError(process, ex, ProcessResources.CouldNotEnumerateModules, "CouldNotEnumerateModules", ErrorCategory.PermissionDenied);619                        }620                    }621                    catch (PipelineStoppedException)622                    {623                        throw;624                    }625                    catch (Exception exception)626                    {627                        WriteNonTerminatingError(process, exception, ProcessResources.CouldNotEnumerateModules, "CouldNotEnumerateModules", ErrorCategory.PermissionDenied);628                    }629                }630                else if (FileVersionInfo.IsPresent)631                {632                    try633                    {634                        ProcessModule mainModule = process.MainModule;635                        if (mainModule != null)636                        {637                            WriteObject(mainModule.FileVersionInfo, true);638                        }639                    }640                    catch (InvalidOperationException exception)641                    {642                        WriteNonTerminatingError(process, exception, ProcessResources.CouldNotEnumerateFileVer, "CouldNotEnumerateFileVer", ErrorCategory.PermissionDenied);643                    }644                    catch (ArgumentException exception)645                    {646                        WriteNonTerminatingError(process, exception, ProcessResources.CouldNotEnumerateFileVer, "CouldNotEnumerateFileVer", ErrorCategory.PermissionDenied);647                    }648                    catch (Win32Exception exception)649                    {650                        try651                        {652                            if (exception.HResult == 299)653                            {654                                WriteObject(process.MainModule?.FileVersionInfo, true);655                            }656                            else657                            {658                                WriteNonTerminatingError(process, exception, ProcessResources.CouldNotEnumerateFileVer, "CouldNotEnumerateFileVer", ErrorCategory.PermissionDenied);659                            }660                        }661                        catch (Win32Exception ex)662                        {663                            WriteNonTerminatingError(process, ex, ProcessResources.CouldNotEnumerateFileVer, "CouldNotEnumerateFileVer", ErrorCategory.PermissionDenied);664                        }665                    }666                    catch (Exception exception)667                    {668                        WriteNonTerminatingError(process, exception, ProcessResources.CouldNotEnumerateFileVer, "CouldNotEnumerateFileVer", ErrorCategory.PermissionDenied);669                    }670                }671                else672                {673                    WriteObject(IncludeUserName.IsPresent ? AddUserNameToProcess(process) : process);674                }675            }676        }677 678        #endregion Overrides679 680        #region Privates681 682        /// <summary>683        /// New PSTypeName added to the process object.684        /// </summary>685        private const string TypeNameForProcessWithUserName = "System.Diagnostics.Process#IncludeUserName";686 687        /// <summary>688        /// Add the 'UserName' NoteProperty to the Process object.689        /// </summary>690        /// <param name="process"></param>691        /// <returns></returns>692        private static PSObject AddUserNameToProcess(Process process)693        {694            // Return null if we failed to get the owner information695            string userName = RetrieveProcessUserName(process);696 697            PSObject processAsPsobj = PSObject.AsPSObject(process);698            PSNoteProperty noteProperty = new("UserName", userName);699 700            processAsPsobj.Properties.Add(noteProperty, true);701            processAsPsobj.TypeNames.Insert(0, TypeNameForProcessWithUserName);702 703            return processAsPsobj;704        }705 706        /// <summary>707        /// Retrieve the UserName through PInvoke.708        /// </summary>709        /// <param name="process"></param>710        /// <returns></returns>711        private static string RetrieveProcessUserName(Process process)712        {713            string userName = null;714#if UNIX715            userName = Platform.NonWindowsGetUserFromPid(process.Id);716#else717            IntPtr tokenUserInfo = IntPtr.Zero;718            IntPtr processTokenHandler = IntPtr.Zero;719 720            const uint TOKEN_QUERY = 0x0008;721 722            try723            {724                int error;725                if (!Win32Native.OpenProcessToken(process.Handle, TOKEN_QUERY, out processTokenHandler))726                {727                    return null;728                }729 730                // Set the default length to be 256, so it will be sufficient for most cases.731                int tokenInfoLength = 256;732                tokenUserInfo = Marshal.AllocHGlobal(tokenInfoLength);733                if (!Win32Native.GetTokenInformation(processTokenHandler, Win32Native.TOKEN_INFORMATION_CLASS.TokenUser, tokenUserInfo, tokenInfoLength, out tokenInfoLength))734                {735                    error = Marshal.GetLastWin32Error();736                    if (error == Win32Native.ERROR_INSUFFICIENT_BUFFER)737                    {738                        Marshal.FreeHGlobal(tokenUserInfo);739                        tokenUserInfo = Marshal.AllocHGlobal(tokenInfoLength);740 741                        if (!Win32Native.GetTokenInformation(processTokenHandler, Win32Native.TOKEN_INFORMATION_CLASS.TokenUser, tokenUserInfo, tokenInfoLength, out tokenInfoLength))742                        {743                            return null;744                        }745                    }746                    else747                    {748                        return null;749                    }750                }751 752                var tokenUser = Marshal.PtrToStructure<Win32Native.TOKEN_USER>(tokenUserInfo);753                SecurityIdentifier sid = new SecurityIdentifier(tokenUser.User.Sid);754                userName = sid.Translate(typeof(System.Security.Principal.NTAccount)).Value;755            }756            catch (NotSupportedException)757            {758                // The Process not started yet, or it's a process from a remote machine.759            }760            catch (IdentityNotMappedException)761            {762                // SID cannot be mapped to a user763            }764            catch (InvalidOperationException)765            {766                // The Process has exited, Process.Handle will raise this exception.767            }768            catch (Win32Exception)769            {770                // We might get an AccessDenied error.771            }772            catch (Exception)773            {774                // I don't expect to get other exceptions.775            }776            finally777            {778                if (tokenUserInfo != IntPtr.Zero)779                {780                    Marshal.FreeHGlobal(tokenUserInfo);781                }782 783                if (processTokenHandler != IntPtr.Zero)784                {785                    Win32Native.CloseHandle(processTokenHandler);786                }787            }788#endif789            return userName;790        }791 792        #endregion Privates793    }794    #endregion GetProcessCommand795 796    #region WaitProcessCommand797    /// <summary>798    /// This class implements the Wait-process command.799    /// </summary>800    [Cmdlet(VerbsLifecycle.Wait, "Process", DefaultParameterSetName = "Name", HelpUri = "https://go.microsoft.com/fwlink/?LinkID=2097146")]801    [OutputType(typeof(Process))]802    public sealed class WaitProcessCommand : ProcessBaseCommand803    {804        #region Parameters805 806        /// <summary>807        /// Specifies the process IDs of the processes to be waited on.808        /// </summary>809        [Parameter(810            ParameterSetName = "Id",811            Position = 0,812            Mandatory = true,813            ValueFromPipelineByPropertyName = true)]814        [ValidateNotNullOrEmpty]815        [Alias("PID", "ProcessId")]816        [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]817        public int[] Id818        {819            get820            {821                return processIds;822            }823 824            set825            {826                myMode = MatchMode.ById;827                processIds = value;828            }829        }830 831        /// <summary>832        /// Name of the processes to wait on for termination.833        /// </summary>834        [Parameter(835            ParameterSetName = "Name",836            Position = 0,837            Mandatory = true,838            ValueFromPipelineByPropertyName = true)]839        [Alias("ProcessName")]840        [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]841        public string[] Name842        {843            get844            {845                return processNames;846            }847 848            set849            {850                myMode = MatchMode.ByName;851                processNames = value;852            }853        }854 855        /// <summary>856        /// If specified, wait for this number of seconds.857        /// </summary>858        [Parameter(Position = 1)]859        [Alias("TimeoutSec")]860        [ValidateNotNullOrEmpty]861        [ValidateRange(0, 32767)]862        public int Timeout863        {864            get865            {866                return _timeout;867            }868 869            set870            {871                _timeout = value;872                _timeOutSpecified = true;873            }874        }875 876        /// <summary>877        /// Gets or sets a value indicating whether to return after any one process exits.878        /// </summary>879        [Parameter]880        public SwitchParameter Any { get; set; }881 882        /// <summary>883        /// Gets or sets a value indicating whether to return the Process objects after waiting.884        /// </summary>885        [Parameter]886        public SwitchParameter PassThru { get; set; }887 888        private int _timeout = 0;889        private bool _timeOutSpecified;890 891        #endregion Parameters892 893        private bool _disposed = false;894 895        #region IDisposable896        /// <summary>897        /// Dispose method of IDisposable interface.898        /// </summary>899        public void Dispose()900        {901            if (!_disposed)902            {903                if (_waitHandle != null)904                {905                    _waitHandle.Dispose();906                    _waitHandle = null;907                }908 909                _disposed = true;910            }911        }912 913        #endregion914 915        #region private methods916        // Handle Exited event and display process information.917        private void myProcess_Exited(object sender, System.EventArgs e)918        {919            if (Any || (Interlocked.Decrement(ref _numberOfProcessesToWaitFor) == 0))920            {921                _waitHandle?.Set();922            }923        }924 925        #endregion926 927        #region Overrides928 929        private readonly List<Process> _processList = new();930 931        // Wait handle which is used by thread to sleep.932        private ManualResetEvent _waitHandle;933        private int _numberOfProcessesToWaitFor;934 935        /// <summary>936        /// Gets the list of process.937        /// </summary>938        protected override void ProcessRecord()939        {940            // adding the processes into the list941            foreach (Process process in MatchingProcesses())942            {943                // Idle process has processid zero,so handle that because we cannot wait on it.944                if (process.Id == 0)945                {946                    WriteNonTerminatingError(process, null, ProcessResources.WaitOnIdleProcess, "WaitOnIdleProcess", ErrorCategory.ObjectNotFound);947                    continue;948                }949 950                // It cannot wait on itself951                if (process.Id.Equals(Environment.ProcessId))952                {953                    WriteNonTerminatingError(process, null, ProcessResources.WaitOnItself, "WaitOnItself", ErrorCategory.ObjectNotFound);954                    continue;955                }956 957                _processList.Add(process);958            }959        }960 961        /// <summary>962        /// Wait for the process to terminate.963        /// </summary>964        protected override void EndProcessing()965        {966            _waitHandle = new ManualResetEvent(false);967            foreach (Process process in _processList)968            {969                try970                {971                    // Check for processes that exit too soon for us to add an event.972                    if (Any && process.HasExited)973                    {974                        _waitHandle.Set();975                    }976                    else if (!process.HasExited)977                    {978                        process.EnableRaisingEvents = true;979                        process.Exited += myProcess_Exited;980                        if (!process.HasExited)981                        {982                            System.Threading.Interlocked.Increment(ref _numberOfProcessesToWaitFor);983                        }984                    }985                }986                catch (Win32Exception exception)987                {988                    WriteNonTerminatingError(process, exception, ProcessResources.ProcessIsNotTerminated, "ProcessNotTerminated", ErrorCategory.CloseError);989                }990            }991 992            bool hasTimedOut = false;993            if (_numberOfProcessesToWaitFor > 0)994            {995                if (_timeOutSpecified)996                {997                    hasTimedOut = !_waitHandle.WaitOne(_timeout * 1000);998                }999                else1000                {1001                    _waitHandle.WaitOne();1002                }1003            }1004 1005            if (hasTimedOut || (!Any && _numberOfProcessesToWaitFor > 0))1006            {1007                foreach (Process process in _processList)1008                {1009                    try1010                    {1011                        if (!process.HasExited)1012                        {1013                            string message = StringUtil.Format(ProcessResources.ProcessNotTerminated, new object[] { process.ProcessName, process.Id });1014                            ErrorRecord errorRecord = new(new TimeoutException(message), "ProcessNotTerminated", ErrorCategory.CloseError, process);1015                            WriteError(errorRecord);1016                        }1017                    }1018                    catch (Win32Exception exception)1019                    {1020                        WriteNonTerminatingError(process, exception, ProcessResources.ProcessIsNotTerminated, "ProcessNotTerminated", ErrorCategory.CloseError);1021                    }1022                }1023            }1024 1025            if (PassThru)1026            {1027                WriteObject(_processList, enumerateCollection: true);1028            }1029        }1030 1031        /// <summary>1032        /// StopProcessing.1033        /// </summary>1034        protected override void StopProcessing() => _waitHandle?.Set();1035 1036        #endregion Overrides1037 1038    }1039    #endregion WaitProcessCommand1040 1041    #region StopProcessCommand1042    /// <summary>1043    /// This class implements the stop-process command.1044    /// </summary>1045    /// <remarks>1046    /// Processes will be sorted before being stopped.  PM confirms1047    /// that this should be fine.1048    /// </remarks>1049    [Cmdlet(VerbsLifecycle.Stop, "Process",1050        DefaultParameterSetName = "Id",1051        SupportsShouldProcess = true, HelpUri = "https://go.microsoft.com/fwlink/?LinkID=2097058")]1052    [OutputType(typeof(Process))]1053    public sealed class StopProcessCommand : ProcessBaseCommand1054    {1055        #region Parameters1056        /// <summary>1057        /// Has the list of process names on which to this command will work.1058        /// </summary>1059        [Parameter(1060            ParameterSetName = "Name",1061            Mandatory = true,1062            ValueFromPipelineByPropertyName = true)]1063        [Alias("ProcessName")]1064        public string[] Name1065        {1066            get1067            {1068                return processNames;1069            }1070 1071            set1072            {1073                processNames = value;1074                myMode = MatchMode.ByName;1075            }1076        }1077 1078        /// <summary>1079        /// Gets/sets an array of process IDs.1080        /// </summary>1081        [Parameter(1082           Position = 0,1083           ParameterSetName = "Id",1084           Mandatory = true,1085           ValueFromPipelineByPropertyName = true)]1086        public int[] Id1087        {1088            get1089            {1090                return processIds;1091            }1092 1093            set1094            {1095                myMode = MatchMode.ById;1096                processIds = value;1097            }1098        }1099 1100        /// <summary>1101        /// Gets/sets an array of objects.1102        /// </summary>1103        [Parameter(1104            Position = 0,1105            ParameterSetName = "InputObject",1106            Mandatory = true,1107            ValueFromPipeline = true)]1108        [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]1109        public new Process[] InputObject1110        {1111            get1112            {1113                return base.InputObject;1114            }1115 1116            set1117            {1118                base.InputObject = value;1119            }1120        }1121 1122        private bool _passThru;1123        /// <summary>1124        /// The updated process object should be passed down the pipeline.1125        /// </summary>1126        [Parameter]1127        public SwitchParameter PassThru1128        {1129            get { return _passThru; }1130 1131            set { _passThru = value; }1132        }1133 1134        /// <summary>1135        /// Specifies whether to force a process to kill1136        /// even if it has dependent services.1137        /// </summary>1138        /// <value></value>1139        [Parameter]1140        [ValidateNotNullOrEmpty]1141        public SwitchParameter Force { get; set; }1142 1143        #endregion Parameters1144 1145        #region Overrides1146        /// <summary>1147        /// Kill the processes.1148        /// It is a non-terminating error if the Process.Kill() operation fails.1149        /// </summary>1150        protected override void ProcessRecord()1151        {1152            if (myMode == MatchMode.All || (myMode == MatchMode.ByName && processNames == null))1153            {1154                Diagnostics.Assert(false, "trying to kill all processes");1155                throw PSTraceSource.NewInvalidOperationException();1156            }1157 1158            foreach (Process process in MatchingProcesses())1159            {1160                // confirm the operation first1161                // this is always false if WhatIf is set1162                // 2005-06-21 Moved this ahead of the hasExited check1163                string targetString = StringUtil.Format(1164                            ProcessResources.ProcessNameForConfirmation,1165                            SafeGetProcessName(process),1166                            SafeGetProcessId(process));1167 1168                if (!ShouldProcess(targetString))1169                {1170                    continue;1171                }1172 1173                try1174                {1175                    // Many properties including Name are not available if the process has exited.1176                    // If this is the case, we skip the process. If the process is from a remote1177                    // machine, then we generate a non-terminating error because .NET doesn't support1178                    // terminate a remote process.1179                    if (process.HasExited)1180                    {1181                        if (PassThru)1182                            WriteObject(process);1183                        continue;1184                    }1185                }1186                catch (NotSupportedException ex)1187                {1188                    WriteNonTerminatingError(1189                        process, ex, ProcessResources.CouldNotStopProcess,1190                        "CouldNotStopProcess", ErrorCategory.InvalidOperation);1191                    continue;1192                }1193                catch (Win32Exception ex)1194                {1195                    WriteNonTerminatingError(1196                        process, ex, ProcessResources.CouldNotStopProcess,1197                        "CouldNotStopProcess", ErrorCategory.CloseError);1198                    continue;1199                }1200 

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