Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
Computer.cs2256 linesDownload Raw Back to management
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4#if !UNIX5 6using System;7using System.Collections;8using System.Collections.Generic;9using System.Collections.ObjectModel;10using System.ComponentModel;11using System.Diagnostics.CodeAnalysis;12using System.Globalization;13using System.IO;14using System.Linq;15using System.Management.Automation;16using System.Management.Automation.Internal;17using System.Net;18using System.Runtime.Serialization;19using System.Security.Cryptography;20using System.Text;21using System.Threading;22using Microsoft.Management.Infrastructure;23using Microsoft.Management.Infrastructure.Options;24using Microsoft.Win32;25using Dbg = System.Management.Automation;26 27namespace Microsoft.PowerShell.Commands28{29    #region Restart-Computer30 31    /// <summary>32    /// This exception is thrown when the timeout expires before a computer finishes restarting.33    /// </summary>34    public sealed class RestartComputerTimeoutException : RuntimeException35    {36        /// <summary>37        /// Name of the computer that is restarting.38        /// </summary>39        public string ComputerName { get; }40 41        /// <summary>42        /// The timeout value specified by the user. It indicates the seconds to wait before timeout.43        /// </summary>44        public int Timeout { get; }45 46        /// <summary>47        /// Construct a RestartComputerTimeoutException.48        /// </summary>49        /// <param name="computerName"></param>50        /// <param name="timeout"></param>51        /// <param name="message"></param>52        /// <param name="errorId"></param>53        internal RestartComputerTimeoutException(string computerName, int timeout, string message, string errorId)54            : base(message)55        {56            SetErrorId(errorId);57            SetErrorCategory(ErrorCategory.OperationTimeout);58            ComputerName = computerName;59            Timeout = timeout;60        }61 62        /// <summary>63        /// Construct a RestartComputerTimeoutException.64        /// </summary>65        public RestartComputerTimeoutException() : base() { }66 67        /// <summary>68        /// Constructs a RestartComputerTimeoutException.69        /// </summary>70        /// <param name="message">71        /// The message used in the exception.72        /// </param>73        public RestartComputerTimeoutException(string message) : base(message) { }74 75        /// <summary>76        /// Constructs a RestartComputerTimeoutException.77        /// </summary>78        /// <param name="message">79        /// The message used in the exception.80        /// </param>81        /// <param name="innerException">82        /// An exception that led to this exception.83        /// </param>84        public RestartComputerTimeoutException(string message, Exception innerException) : base(message, innerException) { }85    }86 87    /// <summary>88    /// Defines the services that Restart-Computer can wait on.89    /// </summary>90    [SuppressMessage("Microsoft.Design", "CA1027:MarkEnumsWithFlags")]91    public enum WaitForServiceTypes92    {93        /// <summary>94        /// Wait for the WMI service to be ready.95        /// </summary>96        Wmi = 0x0,97 98        /// <summary>99        /// Wait for the WinRM service to be ready.100        /// </summary>101        WinRM = 0x1,102 103        /// <summary>104        /// Wait for the PowerShell to be ready.105        /// </summary>106        PowerShell = 0x2,107    }108 109    /// <summary>110    /// Restarts the computer.111    /// </summary>112    [Cmdlet(VerbsLifecycle.Restart, "Computer", SupportsShouldProcess = true, DefaultParameterSetName = DefaultParameterSet,113        HelpUri = "https://go.microsoft.com/fwlink/?LinkID=2097060", RemotingCapability = RemotingCapability.OwnedByCommand)]114    public class RestartComputerCommand : PSCmdlet, IDisposable115    {116        #region "Parameters and PrivateData"117 118        private const string DefaultParameterSet = "DefaultSet";119        private const int forcedReboot = 6; // see https://msdn.microsoft.com/library/aa394058(v=vs.85).aspx120 121        /// <summary>122        /// The authentication options for CIM_WSMan connection.123        /// </summary>124        [Parameter(ParameterSetName = DefaultParameterSet)]125        [ValidateSet(126            "Default",127            "Basic",128            "Negotiate", // can be used with and without credential (without -> PSRP mapped to NegotiateWithImplicitCredential)129            "CredSSP",130            "Digest",131            "Kerberos")] // can be used with explicit or implicit credential132        [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly")]133        public string WsmanAuthentication { get; set; }134 135        /// <summary>136        /// Specifies the computer (s)Name on which this command is executed.137        /// When this parameter is omitted, this cmdlet restarts the local computer.138        /// Type the NETBIOS name, IP address, or fully-qualified domain name of one139        /// or more computers in a comma-separated list. To specify the local computer, type the computername or "localhost".140        /// </summary>141        [Parameter(Position = 0, ValueFromPipeline = true,142                   ValueFromPipelineByPropertyName = true)]143        [ValidateNotNullOrEmpty]144        [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]145        [Alias("CN", "__SERVER", "Server", "IPAddress")]146        public string[] ComputerName { get; set; } = new string[] { "." };147 148        private List<string> _validatedComputerNames = new();149        private readonly List<string> _waitOnComputers = new();150        private readonly HashSet<string> _uniqueComputerNames = new(StringComparer.OrdinalIgnoreCase);151 152        /// <summary>153        /// The following is the definition of the input parameter "Credential".154        /// Specifies a user account that has permission to perform this action. Type a155        /// user-name, such as "User01" or "Domain01\User01", or enter a PSCredential156        /// object, such as one from the Get-Credential cmdlet.157        /// </summary>158        [Parameter(Position = 1)]159        [ValidateNotNullOrEmpty]160        [Credential]161        public PSCredential Credential { get; set; }162 163        /// <summary>164        /// Using Force in conjunction with Reboot on a165        /// remote computer immediately reboots the remote computer.166        /// </summary>167        [Parameter]168        [Alias("f")]169        public SwitchParameter Force { get; set; }170 171        /// <summary>172        /// Specify the Wait parameter. Prompt will be blocked is the Timeout is not 0.173        /// </summary>174        [Parameter(ParameterSetName = DefaultParameterSet)]175        public SwitchParameter Wait { get; set; }176 177        /// <summary>178        /// Specify the Timeout parameter.179        /// Negative value indicates wait infinitely.180        /// Positive value indicates the seconds to wait before timeout.181        /// </summary>182        [Parameter(ParameterSetName = DefaultParameterSet)]183        [Alias("TimeoutSec")]184        [ValidateRange(-1, int.MaxValue)]185        public int Timeout186        {187            get188            {189                return _timeout;190            }191 192            set193            {194                _timeout = value;195                _timeoutSpecified = true;196            }197        }198 199        private int _timeout = -1;200        private bool _timeoutSpecified = false;201 202        /// <summary>203        /// Specify the For parameter.204        /// Wait for the specific service before unblocking the prompt.205        /// </summary>206        [Parameter(ParameterSetName = DefaultParameterSet)]207        public WaitForServiceTypes For208        {209            get210            {211                return _waitFor;212            }213 214            set215            {216                _waitFor = value;217                _waitForSpecified = true;218            }219        }220 221        private WaitForServiceTypes _waitFor = WaitForServiceTypes.PowerShell;222        private bool _waitForSpecified = false;223 224        /// <summary>225        /// Specify the Delay parameter.226        /// The specific time interval (in second) to wait between network pings or service queries.227        /// </summary>228        [Parameter(ParameterSetName = DefaultParameterSet)]229        [ValidateRange(1, short.MaxValue)]230        public short Delay231        {232            get233            {234                return (short)_delay;235            }236 237            set238            {239                _delay = value;240                _delaySpecified = true;241            }242        }243 244        private int _delay = 5;245        private bool _delaySpecified = false;246 247        /// <summary>248        /// Script to test if the PowerShell is ready.249        /// </summary>250        private const string TestPowershellScript = @"251$array = @($input)252$result = @{}253foreach ($computerName in $array[1])254{255    $ret = $null256    $arguments = @{257        ComputerName = $computerName258        ScriptBlock = { $true }259 260        SessionOption = New-PSSessionOption -NoMachineProfile261        ErrorAction = 'SilentlyContinue'262    }263 264    if ( $null -ne $array[0] )265    {266        $arguments['Credential'] = $array[0]267    }268 269    $result[$computerName] = (Invoke-Command @arguments) -as [bool]270}271$result272";273 274        /// <summary>275        /// The indicator to use when show progress.276        /// </summary>277        private readonly string[] _indicator = { "|", "/", "-", "\\" };278 279        /// <summary>280        /// The activity id.281        /// </summary>282        private int _activityId;283 284        /// <summary>285        /// After call 'Shutdown' on the target computer, wait a few286        /// seconds for the restart to begin.287        /// </summary>288        private const int SecondsToWaitForRestartToBegin = 25;289 290        /// <summary>291        /// Actual time out in seconds.292        /// </summary>293        private int _timeoutInMilliseconds;294 295        /// <summary>296        /// Indicate to exit.297        /// </summary>298        private bool _exit, _timeUp;299        private readonly CancellationTokenSource _cancel = new();300 301        /// <summary>302        /// A waithandler to wait on. Current thread will wait on it during the delay interval.303        /// </summary>304        private readonly ManualResetEventSlim _waitHandler = new(false);305        private readonly Dictionary<string, ComputerInfo> _computerInfos = new(StringComparer.OrdinalIgnoreCase);306 307        // CLR 4.0 Port note - use https://msdn.microsoft.com/library/system.net.networkinformation.ipglobalproperties.hostname(v=vs.110).aspx308        private readonly string _shortLocalMachineName = Dns.GetHostName();309 310        // And for this, use PsUtils.GetHostname()311        private readonly string _fullLocalMachineName = Dns.GetHostEntryAsync(string.Empty).Result.HostName;312 313        private int _percent;314        private string _status;315        private string _activity;316        private Timer _timer;317        private System.Management.Automation.PowerShell _powershell;318 319        private const string StageVerification = "VerifyStage";320        private const string WmiConnectionTest = "WMI";321        private const string WinrmConnectionTest = "WinRM";322        private const string PowerShellConnectionTest = "PowerShell";323 324        #endregion "parameters and PrivateData"325 326        #region "IDisposable Members"327 328        /// <summary>329        /// Dispose Method.330        /// </summary>331        public void Dispose()332        {333            this.Dispose(true);334            // Use SuppressFinalize in case a subclass335            // of this type implements a finalizer.336            GC.SuppressFinalize(this);337        }338 339        /// <summary>340        /// Dispose Method.341        /// </summary>342        /// <param name="disposing"></param>343        public void Dispose(bool disposing)344        {345            if (disposing)346            {347                _timer?.Dispose();348                _waitHandler.Dispose();349                _cancel.Dispose();350                _powershell?.Dispose();351            }352        }353 354        #endregion "IDisposable Members"355 356        #region "Private Methods"357 358        /// <summary>359        /// Validate parameters for 'DefaultSet'360        /// 1. When the Wait is specified, the computername cannot contain the local machine361        /// 2. If the local machine is present, make sure it is at the end of the list (so the remote ones get restarted before the local machine reboot).362        /// </summary>363        private void ValidateComputerNames()364        {365            bool containLocalhost = false;366            _validatedComputerNames.Clear();367 368            foreach (string name in ComputerName)369            {370                ErrorRecord error = null;371                string targetComputerName = ComputerWMIHelper.ValidateComputerName(name, _shortLocalMachineName, _fullLocalMachineName, ref error);372                if (targetComputerName == null)373                {374                    if (error != null)375                    {376                        WriteError(error);377                    }378 379                    continue;380                }381 382                if (targetComputerName.Equals(ComputerWMIHelper.localhostStr, StringComparison.OrdinalIgnoreCase))383                {384                    containLocalhost = true;385                }386                else if (!_uniqueComputerNames.Contains(targetComputerName))387                {388                    _validatedComputerNames.Add(targetComputerName);389                    _uniqueComputerNames.Add(targetComputerName);390                }391            }392 393            // Force wait with a test hook even if we're on the local computer394            if (!InternalTestHooks.TestWaitStopComputer && Wait && containLocalhost)395            {396                // The local machine will be ignored, and an error will be emitted.397                InvalidOperationException ex = new(ComputerResources.CannotWaitLocalComputer);398                WriteError(new ErrorRecord(ex, "CannotWaitLocalComputer", ErrorCategory.InvalidOperation, null));399                containLocalhost = false;400            }401 402            // Add the localhost to the end of the list, so we will restart remote machines403            // before we restart the local one.404            if (containLocalhost)405            {406                _validatedComputerNames.Add(ComputerWMIHelper.localhostStr);407            }408        }409 410        /// <summary>411        /// Write out progress.412        /// </summary>413        /// <param name="activity"></param>414        /// <param name="status"></param>415        /// <param name="percent"></param>416        /// <param name="progressRecordType"></param>417        private void WriteProgress(string activity, string status, int percent, ProgressRecordType progressRecordType)418        {419            ProgressRecord progress = new(_activityId, activity, status);420            progress.PercentComplete = percent;421            progress.RecordType = progressRecordType;422            WriteProgress(progress);423        }424 425        /// <summary>426        /// Calculate the progress percentage.427        /// </summary>428        /// <param name="currentStage"></param>429        /// <returns></returns>430        private int CalculateProgressPercentage(string currentStage)431        {432            switch (currentStage)433            {434                case StageVerification:435                    return _waitFor.Equals(WaitForServiceTypes.Wmi) || _waitFor.Equals(WaitForServiceTypes.WinRM)436                               ? 33437                               : 20;438                case WmiConnectionTest:439                    return _waitFor.Equals(WaitForServiceTypes.Wmi) ? 66 : 40;440                case WinrmConnectionTest:441                    return _waitFor.Equals(WaitForServiceTypes.WinRM) ? 66 : 60;442                case PowerShellConnectionTest:443                    return 80;444                default:445                    break;446            }447 448            Dbg.Diagnostics.Assert(false, "CalculateProgressPercentage should never hit the default case");449            return 0;450        }451 452        /// <summary>453        /// Event handler for the timer.454        /// </summary>455        /// <param name="s"></param>456        private void OnTimedEvent(object s)457        {458            _exit = _timeUp = true;459            _cancel.Cancel();460            _waitHandler.Set();461 462            if (_powershell != null)463            {464                _powershell.Stop();465                _powershell.Dispose();466            }467        }468 469        private sealed class ComputerInfo470        {471            internal string LastBootUpTime;472            internal bool RebootComplete;473        }474 475        private List<string> TestRestartStageUsingWsman(IEnumerable<string> computerNames, List<string> nextTestList, CancellationToken token)476        {477            var restartStageTestList = new List<string>();478            var operationOptions = new CimOperationOptions479            {480                Timeout = TimeSpan.FromMilliseconds(2000),481                CancellationToken = token482            };483            foreach (var computer in computerNames)484            {485                try486                {487                    if (token.IsCancellationRequested)488                    {489                        break;490                    }491 492                    using (CimSession cimSession = RemoteDiscoveryHelper.CreateCimSession(computer, Credential, WsmanAuthentication, isLocalHost: false, this, token))493                    {494                        bool itemRetrieved = false;495                        IEnumerable<CimInstance> mCollection = cimSession.QueryInstances(496                                                                 ComputerWMIHelper.CimOperatingSystemNamespace,497                                                                 ComputerWMIHelper.CimQueryDialect,498                                                                 "Select * from " + ComputerWMIHelper.WMI_Class_OperatingSystem,499                                                                 operationOptions);500                        foreach (CimInstance os in mCollection)501                        {502                            itemRetrieved = true;503                            string newLastBootUpTime = os.CimInstanceProperties["LastBootUpTime"].Value.ToString();504                            string oldLastBootUpTime = _computerInfos[computer].LastBootUpTime;505 506                            if (!string.Equals(newLastBootUpTime, oldLastBootUpTime, StringComparison.OrdinalIgnoreCase))507                            {508                                _computerInfos[computer].RebootComplete = true;509                                nextTestList.Add(computer);510                            }511                            else512                            {513                                restartStageTestList.Add(computer);514                            }515                        }516 517                        if (!itemRetrieved)518                        {519                            restartStageTestList.Add(computer);520                        }521                    }522                }523                catch (CimException)524                {525                    restartStageTestList.Add(computer);526                }527                catch (Exception)528                {529                    restartStageTestList.Add(computer);530                }531            }532 533            return restartStageTestList;534        }535 536        private List<string> SetUpComputerInfoUsingWsman(IEnumerable<string> computerNames, CancellationToken token)537        {538            var validComputerNameList = new List<string>();539            var operationOptions = new CimOperationOptions540            {541                Timeout = TimeSpan.FromMilliseconds(2000),542                CancellationToken = token543            };544            foreach (var computer in computerNames)545            {546                try547                {548                    using (CimSession cimSession = RemoteDiscoveryHelper.CreateCimSession(computer, Credential, WsmanAuthentication, isLocalHost: false, this, token))549                    {550                        bool itemRetrieved = false;551                        IEnumerable<CimInstance> mCollection = cimSession.QueryInstances(552                                                                 ComputerWMIHelper.CimOperatingSystemNamespace,553                                                                 ComputerWMIHelper.CimQueryDialect,554                                                                 "Select * from " + ComputerWMIHelper.WMI_Class_OperatingSystem,555                                                                 operationOptions);556                        foreach (CimInstance os in mCollection)557                        {558                            itemRetrieved = true;559                            if (!_computerInfos.ContainsKey(computer))560                            {561                                var info = new ComputerInfo562                                {563                                    LastBootUpTime = os.CimInstanceProperties["LastBootUpTime"].Value.ToString(),564                                    RebootComplete = false565                                };566                                _computerInfos.Add(computer, info);567                                validComputerNameList.Add(computer);568                            }569                        }570 571                        if (!itemRetrieved)572                        {573                            string errMsg = StringUtil.Format(ComputerResources.RestartComputerSkipped, computer, ComputerResources.CannotGetOperatingSystemObject);574                            var error = new ErrorRecord(new InvalidOperationException(errMsg), "RestartComputerSkipped",575                                                            ErrorCategory.OperationStopped, computer);576                            this.WriteError(error);577                        }578                    }579                }580                catch (CimException ex)581                {582                    string errMsg = StringUtil.Format(ComputerResources.RestartComputerSkipped, computer, ex.Message);583                    var error = new ErrorRecord(new InvalidOperationException(errMsg), "RestartComputerSkipped",584                                                        ErrorCategory.OperationStopped, computer);585                    this.WriteError(error);586                }587                catch (Exception ex)588                {589                    string errMsg = StringUtil.Format(ComputerResources.RestartComputerSkipped, computer, ex.Message);590                    var error = new ErrorRecord(new InvalidOperationException(errMsg), "RestartComputerSkipped",591                                                        ErrorCategory.OperationStopped, computer);592                    this.WriteError(error);593                }594            }595 596            return validComputerNameList;597        }598 599        private void WriteOutTimeoutError(IEnumerable<string> computerNames)600        {601            const string errorId = "RestartComputerTimeout";602            foreach (string computer in computerNames)603            {604                string errorMsg = StringUtil.Format(ComputerResources.RestartcomputerFailed, computer, ComputerResources.TimeoutError);605                var exception = new RestartComputerTimeoutException(computer, Timeout, errorMsg, errorId);606                var error = new ErrorRecord(exception, errorId, ErrorCategory.OperationTimeout, computer);607                if (!InternalTestHooks.TestWaitStopComputer)608                {609                    WriteError(error);610                }611            }612        }613 614        #endregion "Private Methods"615 616        #region "Internal Methods"617 618        internal static List<string> TestWmiConnectionUsingWsman(List<string> computerNames, List<string> nextTestList, PSCredential credential, string wsmanAuthentication, PSCmdlet cmdlet, CancellationToken token)619        {620            // Check if the WMI service "Winmgmt" is started621            const string wmiServiceQuery = "Select * from " + ComputerWMIHelper.WMI_Class_Service + " Where name = 'Winmgmt'";622            var wmiTestList = new List<string>();623            var operationOptions = new CimOperationOptions624            {625                Timeout = TimeSpan.FromMilliseconds(2000),626                CancellationToken = token627            };628            foreach (var computer in computerNames)629            {630                try631                {632                    if (token.IsCancellationRequested)633                    {634                        break;635                    }636 637                    using (CimSession cimSession = RemoteDiscoveryHelper.CreateCimSession(computer, credential, wsmanAuthentication, isLocalHost: false, cmdlet, token))638                    {639                        bool itemRetrieved = false;640                        IEnumerable<CimInstance> mCollection = cimSession.QueryInstances(641                                                                 ComputerWMIHelper.CimOperatingSystemNamespace,642                                                                 ComputerWMIHelper.CimQueryDialect,643                                                                 wmiServiceQuery,644                                                                 operationOptions);645                        foreach (CimInstance service in mCollection)646                        {647                            itemRetrieved = true;648                            if (LanguagePrimitives.IsTrue(service.CimInstanceProperties["Started"].Value))649                            {650                                nextTestList.Add(computer);651                            }652                            else653                            {654                                wmiTestList.Add(computer);655                            }656                        }657 658                        if (!itemRetrieved)659                        {660                            wmiTestList.Add(computer);661                        }662                    }663                }664                catch (CimException)665                {666                    wmiTestList.Add(computer);667                }668                catch (Exception)669                {670                    wmiTestList.Add(computer);671                }672            }673 674            return wmiTestList;675        }676 677        /// <summary>678        /// Test the PowerShell state for the restarting computer.679        /// </summary>680        /// <param name="computerNames"></param>681        /// <param name="nextTestList"></param>682        /// <param name="powershell"></param>683        /// <param name="credential"></param>684        /// <returns></returns>685        internal static List<string> TestPowerShell(List<string> computerNames, List<string> nextTestList, System.Management.Automation.PowerShell powershell, PSCredential credential)686        {687            List<string> psList = new();688 689            try690            {691                Collection<PSObject> psObjectCollection = powershell.Invoke(new object[] { credential, computerNames.ToArray() });692                if (psObjectCollection == null)693                {694                    Dbg.Diagnostics.Assert(false, "This should never happen. Invoke should never return null.");695                }696 697                // If ^C or timeout happens when we are in powershell.Invoke(), the psObjectCollection might be empty698                if (psObjectCollection.Count == 0)699                {700                    return computerNames;701                }702 703                object result = PSObject.Base(psObjectCollection[0]);704                Hashtable data = result as Hashtable;705 706                Dbg.Diagnostics.Assert(data != null, "data should never be null");707                Dbg.Diagnostics.Assert(data.Count == computerNames.Count, "data should contain results for all computers in computerNames");708 709                foreach (string computer in computerNames)710                {711                    if (LanguagePrimitives.IsTrue(data[computer]))712                    {713                        nextTestList.Add(computer);714                    }715                    else716                    {717                        psList.Add(computer);718                    }719                }720            }721            catch (PipelineStoppedException)722            {723                // powershell.Stop() is invoked because timeout expires, or Ctrl+C is pressed724            }725            catch (ObjectDisposedException)726            {727                // powershell.dispose() is invoked because timeout expires, or Ctrl+C is pressed728            }729 730            return psList;731        }732 733        #endregion "Internal Methods"734 735        #region "Overrides"736 737        /// <summary>738        /// BeginProcessing method.739        /// </summary>740        protected override void BeginProcessing()741        {742            // Timeout, For, Delay, Progress cannot be present if Wait is not present743            if ((_timeoutSpecified || _waitForSpecified || _delaySpecified) && !Wait)744            {745                InvalidOperationException ex = new(ComputerResources.RestartComputerInvalidParameter);746                ThrowTerminatingError(new ErrorRecord(ex, "RestartComputerInvalidParameter", ErrorCategory.InvalidOperation, null));747            }748 749            if (Wait)750            {751                _activityId = Random.Shared.Next();752                if (_timeout == -1 || _timeout >= int.MaxValue / 1000)753                {754                    _timeoutInMilliseconds = int.MaxValue;755                }756                else757                {758                    _timeoutInMilliseconds = _timeout * 1000;759                }760 761                // We don't support combined service types for now762                switch (_waitFor)763                {764                    case WaitForServiceTypes.Wmi:765                    case WaitForServiceTypes.WinRM:766                        break;767                    case WaitForServiceTypes.PowerShell:768                        _powershell = System.Management.Automation.PowerShell.Create();769                        _powershell.AddScript(TestPowershellScript);770                        break;771                    default:772                        InvalidOperationException ex = new(ComputerResources.NoSupportForCombinedServiceType);773                        ErrorRecord error = new(ex, "NoSupportForCombinedServiceType", ErrorCategory.InvalidOperation, (int)_waitFor);774                        ThrowTerminatingError(error);775                        break;776                }777            }778        }779 780        /// <summary>781        /// ProcessRecord method.782        /// </summary>783        [SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling")]784        protected override void ProcessRecord()785        {786            // Validate parameters787            ValidateComputerNames();788 789            object[] flags = new object[] { 2, 0 };790            if (Force)791            {792                flags[0] = forcedReboot;793            }794 795            if (ParameterSetName.Equals(DefaultParameterSet, StringComparison.OrdinalIgnoreCase))796            {797                if (Wait && _timeout != 0)798                {799                    _validatedComputerNames =800                        SetUpComputerInfoUsingWsman(_validatedComputerNames, _cancel.Token);801                }802 803                foreach (string computer in _validatedComputerNames)804                {805                    bool isLocal = false;806                    string compname;807 808                    if (computer.Equals("localhost", StringComparison.OrdinalIgnoreCase))809                    {810                        compname = _shortLocalMachineName;811                        isLocal = true;812                    }813                    else814                    {815                        compname = computer;816                    }817 818                    // Generate target and action strings819                    string action =820                        StringUtil.Format(821                            ComputerResources.RestartComputerAction,822                            isLocal ? ComputerResources.LocalShutdownPrivilege : ComputerResources.RemoteShutdownPrivilege);823                    string target =824                        isLocal ? StringUtil.Format(ComputerResources.DoubleComputerName, "localhost", compname) : compname;825 826                    if (!ShouldProcess(target, action))827                    {828                        continue;829                    }830 831                    bool isSuccess =832                        ComputerWMIHelper.InvokeWin32ShutdownUsingWsman(this, isLocal, compname, flags, Credential, WsmanAuthentication, ComputerResources.RestartcomputerFailed, "RestartcomputerFailed", _cancel.Token);833 834                    if (isSuccess && Wait && _timeout != 0)835                    {836                        _waitOnComputers.Add(computer);837                    }838                }839 840                if (_waitOnComputers.Count > 0)841                {842                    var restartStageTestList = new List<string>(_waitOnComputers);843                    var wmiTestList = new List<string>();844                    var winrmTestList = new List<string>();845                    var psTestList = new List<string>();846                    var allDoneList = new List<string>();847 848                    bool isForWmi = _waitFor.Equals(WaitForServiceTypes.Wmi);849                    bool isForWinRm = _waitFor.Equals(WaitForServiceTypes.WinRM);850                    bool isForPowershell = _waitFor.Equals(WaitForServiceTypes.PowerShell);851 852                    int indicatorIndex = 0;853                    int machineCompleteRestart = 0;854                    int actualDelay = SecondsToWaitForRestartToBegin;855                    bool first = true;856                    bool waitComplete = false;857 858                    _percent = 0;859                    _status = ComputerResources.WaitForRestartToBegin;860                    _activity = _waitOnComputers.Count == 1 ?861                        StringUtil.Format(ComputerResources.RestartSingleComputerActivity, _waitOnComputers[0]) :862                        ComputerResources.RestartMultipleComputersActivity;863 864                    _timer = new Timer(OnTimedEvent, null, _timeoutInMilliseconds, System.Threading.Timeout.Infinite);865 866                    while (true)867                    {868                        // (delay * 1000)/250ms869                        int loopCount = actualDelay * 4;870                        while (loopCount > 0)871                        {872                            WriteProgress(_indicator[(indicatorIndex++) % 4] + _activity, _status, _percent, ProgressRecordType.Processing);873 874                            loopCount--;875                            _waitHandler.Wait(250);876                            if (_exit)877                            {878                                break;879                            }880                        }881 882                        if (first)883                        {884                            actualDelay = _delay;885                            first = false;886 887                            if (_waitOnComputers.Count > 1)888                            {889                                _status = StringUtil.Format(ComputerResources.WaitForMultipleComputers, machineCompleteRestart, _waitOnComputers.Count);890                                WriteProgress(_indicator[(indicatorIndex++) % 4] + _activity, _status, _percent, ProgressRecordType.Processing);891                            }892                        }893 894                        do895                        {896                            // Test restart stage.897                            // We check if the target machine has already rebooted by querying the LastBootUpTime from the Win32_OperatingSystem object.898                            // So after this step, we are sure that both the Network and the WMI or WinRM service have already come up.899                            if (_exit)900                            {901                                break;902                            }903 904                            if (restartStageTestList.Count > 0)905                            {906                                if (_waitOnComputers.Count == 1)907                                {908                                    _status = ComputerResources.VerifyRebootStage;909                                    _percent = CalculateProgressPercentage(StageVerification);910                                    WriteProgress(_indicator[(indicatorIndex++) % 4] + _activity, _status, _percent, ProgressRecordType.Processing);911                                }912 913                                List<string> nextTestList = (isForWmi || isForPowershell) ? wmiTestList : winrmTestList;914                                restartStageTestList = TestRestartStageUsingWsman(restartStageTestList, nextTestList, _cancel.Token);915                            }916 917                            // Test WMI service918                            if (_exit)919                            {920                                break;921                            }922 923                            if (wmiTestList.Count > 0)924                            {925                                // This statement block executes for both CLRs.926                                // In the "full" CLR, it serves as the else case.927                                {928                                    if (_waitOnComputers.Count == 1)929                                    {930                                        _status = ComputerResources.WaitForWMI;931                                        _percent = CalculateProgressPercentage(WmiConnectionTest);932                                        WriteProgress(_indicator[(indicatorIndex++) % 4] + _activity, _status, _percent, ProgressRecordType.Processing);933                                    }934 935                                    wmiTestList = TestWmiConnectionUsingWsman(wmiTestList, winrmTestList, Credential, WsmanAuthentication, this, _cancel.Token);936                                }937                            }938 939                            if (isForWmi)940                            {941                                break;942                            }943 944                            // Test WinRM service945                            if (_exit)946                            {947                                break;948                            }949 950                            if (winrmTestList.Count > 0)951                            {952                                // This statement block executes for both CLRs.953                                // In the "full" CLR, it serves as the else case.954                                {955                                    // CIM-WSMan in use. In this case, restart stage checking is done by using WMIv2,956                                    // so the WinRM service on the target machine is already up at this point.957                                    psTestList.AddRange(winrmTestList);958                                    winrmTestList.Clear();959 960                                    if (_waitOnComputers.Count == 1)961                                    {962                                        // This is to simulate the test for WinRM service963                                        _status = ComputerResources.WaitForWinRM;964                                        _percent = CalculateProgressPercentage(WinrmConnectionTest);965 966                                        loopCount = actualDelay * 4; // (delay * 1000)/250ms967                                        while (loopCount > 0)968                                        {969                                            WriteProgress(_indicator[(indicatorIndex++) % 4] + _activity, _status, _percent, ProgressRecordType.Processing);970 971                                            loopCount--;972                                            _waitHandler.Wait(250);973                                            if (_exit)974                                            {975                                                break;976                                            }977                                        }978                                    }979                                }980                            }981 982                            if (isForWinRm)983                            {984                                break;985                            }986 987                            // Test PowerShell988                            if (_exit)989                            {990                                break;991                            }992 993                            if (psTestList.Count > 0)994                            {995                                if (_waitOnComputers.Count == 1)996                                {997                                    _status = ComputerResources.WaitForPowerShell;998                                    _percent = CalculateProgressPercentage(PowerShellConnectionTest);999                                    WriteProgress(_indicator[(indicatorIndex++) % 4] + _activity, _status, _percent, ProgressRecordType.Processing);1000                                }1001 1002                                psTestList = TestPowerShell(psTestList, allDoneList, _powershell, this.Credential);1003                            }1004                        } while (false);1005 1006                        // if time is up or Ctrl+c is typed, break out1007                        if (_exit)1008                        {1009                            break;1010                        }1011 1012                        // Check if the restart completes1013                        switch (_waitFor)1014                        {1015                            case WaitForServiceTypes.Wmi:1016                                waitComplete = (winrmTestList.Count == _waitOnComputers.Count);1017                                machineCompleteRestart = winrmTestList.Count;1018                                break;1019                            case WaitForServiceTypes.WinRM:1020                                waitComplete = (psTestList.Count == _waitOnComputers.Count);1021                                machineCompleteRestart = psTestList.Count;1022                                break;1023                            case WaitForServiceTypes.PowerShell:1024                                waitComplete = (allDoneList.Count == _waitOnComputers.Count);1025                                machineCompleteRestart = allDoneList.Count;1026                                break;1027                        }1028 1029                        // Wait is done or time is up1030                        if (waitComplete || _exit)1031                        {1032                            if (waitComplete)1033                            {1034                                _status = ComputerResources.RestartComplete;1035                                WriteProgress(_indicator[indicatorIndex % 4] + _activity, _status, 100, ProgressRecordType.Completed);1036                                _timer.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);1037                            }1038 1039                            break;1040                        }1041 1042                        if (_waitOnComputers.Count > 1)1043                        {1044                            _status = StringUtil.Format(ComputerResources.WaitForMultipleComputers, machineCompleteRestart, _waitOnComputers.Count);1045                            _percent = machineCompleteRestart * 100 / _waitOnComputers.Count;1046                        }1047                    }1048 1049                    if (_timeUp)1050                    {1051                        // The timeout expires. Write out timeout error messages for the computers that haven't finished restarting1052                        do1053                        {1054                            if (restartStageTestList.Count > 0)1055                            {1056                                WriteOutTimeoutError(restartStageTestList);1057                            }1058 1059                            if (wmiTestList.Count > 0)1060                            {1061                                WriteOutTimeoutError(wmiTestList);1062                            }1063 1064                            // Wait for WMI. All computers that finished restarting are put in "winrmTestList"1065                            if (isForWmi)1066                            {1067                                break;1068                            }1069 1070                            // Wait for WinRM. All computers that finished restarting are put in "psTestList"1071                            if (winrmTestList.Count > 0)1072                            {1073                                WriteOutTimeoutError(winrmTestList);1074                            }1075 1076                            if (isForWinRm)1077                            {1078                                break;1079                            }1080 1081                            if (psTestList.Count > 0)1082                            {1083                                WriteOutTimeoutError(psTestList);1084                            }1085 1086                            // Wait for PowerShell. All computers that finished restarting are put in "allDoneList"1087                        } while (false);1088                    }1089                }1090            }1091        }1092 1093        /// <summary>1094        /// To implement ^C.1095        /// </summary>1096        protected override void StopProcessing()1097        {1098            _exit = true;1099            _cancel.Cancel();1100            _waitHandler.Set();1101 1102            _timer?.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);1103 1104            if (_powershell != null)1105            {1106                _powershell.Stop();1107                _powershell.Dispose();1108            }1109        }1110 1111        #endregion "Overrides"1112    }1113 1114    #endregion Restart-Computer1115 1116    #region Stop-Computer1117 1118    /// <summary>1119    /// Cmdlet to stop computer.1120    /// </summary>1121    [Cmdlet(VerbsLifecycle.Stop, "Computer", SupportsShouldProcess = true,1122        HelpUri = "https://go.microsoft.com/fwlink/?LinkID=2097151", RemotingCapability = RemotingCapability.SupportedByCommand)]1123    public sealed class StopComputerCommand : PSCmdlet, IDisposable1124    {1125        #region Private Members1126 1127        private readonly CancellationTokenSource _cancel = new();1128 1129        private const int forcedShutdown = 5; // See https://msdn.microsoft.com/library/aa394058(v=vs.85).aspx1130 1131        #endregion1132 1133        #region "Parameters"1134 1135        /// <summary>1136        /// The authentication options for CIM_WSMan connection.1137        /// </summary>1138        [Parameter]1139        [ValidateSet(1140            "Default",1141            "Basic",1142            "Negotiate", // can be used with and without credential (without -> PSRP mapped to NegotiateWithImplicitCredential)1143            "CredSSP",1144            "Digest",1145            "Kerberos")] // can be used with explicit or implicit credential1146        [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly")]1147        public string WsmanAuthentication { get; set; } = "Default";1148 1149        /// <summary>1150        /// The following is the definition of the input parameter "ComputerName".1151        /// Value of the address requested. The form of the value can be either the1152        /// computer name ("wxyz1234"), IPv4 address ("192.168.177.124"), or IPv61153        /// address ("2010:836B:4179::836B:4179").1154        /// </summary>1155        [Parameter(Position = 0, ValueFromPipelineByPropertyName = true)]1156        [ValidateNotNullOrEmpty]1157        [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]1158        [Alias("CN", "__SERVER", "Server", "IPAddress")]1159        public string[] ComputerName { get; set; } = new string[] { "." };1160 1161        /// <summary>1162        /// The following is the definition of the input parameter "Credential".1163        /// Specifies a user account that has permission to perform this action. Type a1164        /// user-name, such as "User01" or "Domain01\User01", or enter a PSCredential1165        /// object, such as one from the Get-Credential cmdlet.1166        /// </summary>1167        [Parameter(Position = 1)]1168        [ValidateNotNullOrEmpty]1169        [Credential]1170        public PSCredential Credential { get; set; }1171 1172        /// <summary>1173        /// Force the operation to take place if possible.1174        /// </summary>1175        [Parameter]1176        public SwitchParameter Force { get; set; } = false;1177 1178        #endregion "parameters"1179 1180        #region "IDisposable Members"1181 1182        /// <summary>1183        /// Dispose Method.1184        /// </summary>1185        public void Dispose()1186        {1187            _cancel.Dispose();1188        }1189 1190        #endregion "IDisposable Members"1191 1192        #region "Overrides"1193 1194        /// <summary>1195        /// ProcessRecord.1196        /// </summary>1197        [SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling")]1198        protected override void ProcessRecord()1199        {1200            object[] flags = new object[] { 1, 0 };

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