Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
History.cs1903 linesDownload Raw Back to hostifaces
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System;5using System.Collections.Generic;6using System.Collections.ObjectModel;7using System.Diagnostics.CodeAnalysis;8using System.Globalization;9using System.IO;10using System.Management.Automation;11using System.Management.Automation.Host;12using System.Management.Automation.Internal;13using System.Management.Automation.Runspaces;14 15using Dbg = System.Management.Automation.Diagnostics;16 17namespace Microsoft.PowerShell.Commands18{19    /// <summary>20    /// Contains information about a single history entry.21    /// </summary>22    public class HistoryInfo23    {24        /// <summary>25        /// Constructor.26        /// </summary>27        /// <param name="pipelineId">Id of pipeline in which command associated28        /// with this history entry is executed</param>29        /// <param name="cmdline">Command string.</param>30        /// <param name="status">Status of pipeline execution.</param>31        /// <param name="startTime">StartTime of execution.</param>32        /// <param name="endTime">EndTime of execution.</param>33        internal HistoryInfo(long pipelineId, string cmdline, PipelineState status, DateTime startTime, DateTime endTime)34        {35            Dbg.Assert(cmdline != null, "caller should validate the parameter");36            _pipelineId = pipelineId;37            CommandLine = cmdline;38            ExecutionStatus = status;39            StartExecutionTime = startTime;40            EndExecutionTime = endTime;41            Cleared = false;42        }43 44        /// <summary>45        /// Copy constructor to support cloning.46        /// </summary>47        /// <param name="history"></param>48        private HistoryInfo(HistoryInfo history)49        {50            Id = history.Id;51            _pipelineId = history._pipelineId;52            CommandLine = history.CommandLine;53            ExecutionStatus = history.ExecutionStatus;54            StartExecutionTime = history.StartExecutionTime;55            EndExecutionTime = history.EndExecutionTime;56            Cleared = history.Cleared;57        }58 59        /// <summary>60        /// Id of this history entry.61        /// </summary>62        /// <value></value>63        public long Id { get; private set; }64 65        /// <summary>66        /// CommandLine string.67        /// </summary>68        /// <value></value>69        public string CommandLine { get; private set; }70 71        /// <summary>72        /// Execution status of associated pipeline.73        /// </summary>74        /// <value></value>75        public PipelineState ExecutionStatus { get; private set; }76 77        /// <summary>78        /// Start time of execution of associated pipeline.79        /// </summary>80        /// <value></value>81        public DateTime StartExecutionTime { get; }82 83        /// <summary>84        /// End time of execution of associated pipeline.85        /// </summary>86        /// <value></value>87        public DateTime EndExecutionTime { get; private set; }88 89        /// <summary>90        /// The time it took to execute the associeated pipeline.91        /// </summary>92        public TimeSpan Duration => EndExecutionTime - StartExecutionTime;93 94        /// <summary>95        /// Override for ToString() method.96        /// </summary>97        /// <returns></returns>98        public override string ToString()99        {100            if (string.IsNullOrEmpty(CommandLine))101            {102                return base.ToString();103            }104            else105            {106                return CommandLine;107            }108        }109 110        /// <summary>111        /// Cleared status of an entry.112        /// </summary>113        internal bool Cleared { get; set; } = false;114 115        /// <summary>116        /// Sets Id.117        /// </summary>118        /// <param name="id"></param>119        internal void SetId(long id) => Id = id;120 121        /// <summary>122        /// Set status.123        /// </summary>124        /// <param name="status"></param>125        internal void SetStatus(PipelineState status) => ExecutionStatus = status;126 127        /// <summary>128        /// Set endtime.129        /// </summary>130        /// <param name="endTime"></param>131        internal void SetEndTime(DateTime endTime) => EndExecutionTime = endTime;132 133        /// <summary>134        /// Sets command.135        /// </summary>136        /// <param name="command"></param>137        internal void SetCommand(string command) => CommandLine = command;138 139        /// <summary>140        /// Id of the pipeline corresponding to this history entry.141        /// </summary>142        private readonly long _pipelineId;143 144        /// <summary>145        /// Returns a clone of this object.146        /// </summary>147        /// <returns></returns>148        public HistoryInfo Clone()149        {150            return new HistoryInfo(this);151        }152    }153 154    /// <summary>155    /// This class implements history and provides APIs for adding and fetching156    /// entries from history.157    /// </summary>158    internal class History159    {160        /// <summary>161        /// Default history size.162        /// </summary>163        internal const int DefaultHistorySize = 4096;164 165        #region constructors166 167        /// <summary>168        /// Constructs history store.169        /// </summary>170        internal History(ExecutionContext context)171        {172            // Create history size variable. Add ValidateRangeAttribute to173            // validate the range.174            Collection<Attribute> attrs = new Collection<Attribute>();175            attrs.Add(new ValidateRangeAttribute(1, (int)Int16.MaxValue));176            PSVariable historySizeVar = new PSVariable(SpecialVariables.HistorySize, DefaultHistorySize, ScopedItemOptions.None, attrs);177            historySizeVar.Description = SessionStateStrings.MaxHistoryCountDescription;178 179            context.EngineSessionState.SetVariable(historySizeVar, false, CommandOrigin.Internal);180 181            _capacity = DefaultHistorySize;182            _buffer = new HistoryInfo[_capacity];183        }184 185        #endregion constructors186 187        #region internal188 189        /// <summary>190        /// Create a new history entry.191        /// </summary>192        /// <param name="pipelineId"></param>193        /// <param name="cmdline"></param>194        /// <param name="status"></param>195        /// <param name="startTime"></param>196        /// <param name="endTime"></param>197        /// <param name="skipIfLocked">If true, the entry will not be added when the history is locked.</param>198        /// <returns>Id for the new created entry. Use this id to fetch the199        /// entry. Returns -1 if the entry is not added.</returns>200        /// <remarks>This function is thread safe</remarks>201        internal long AddEntry(long pipelineId, string cmdline, PipelineState status, DateTime startTime, DateTime endTime, bool skipIfLocked)202        {203            if (!System.Threading.Monitor.TryEnter(_syncRoot, skipIfLocked ? 0 : System.Threading.Timeout.Infinite))204            {205                return -1;206            }207 208            try209            {210                ReallocateBufferIfNeeded();211 212                HistoryInfo entry = new HistoryInfo(pipelineId, cmdline, status, startTime, endTime);213                return Add(entry);214            }215            finally216            {217                System.Threading.Monitor.Exit(_syncRoot);218            }219        }220 221        /// <summary>222        /// Update the history entry corresponding to id.223        /// </summary>224        /// <param name="id">Id of history entry to be updated.</param>225        /// <param name="status">Status to be updated.</param>226        /// <param name="endTime">EndTime to be updated.</param>227        /// <param name="skipIfLocked">If true, the entry will not be added when the history is locked.</param>228        /// <returns></returns>229        internal void UpdateEntry(long id, PipelineState status, DateTime endTime, bool skipIfLocked)230        {231            if (!System.Threading.Monitor.TryEnter(_syncRoot, skipIfLocked ? 0 : System.Threading.Timeout.Infinite))232            {233                return;234            }235 236            try237            {238                HistoryInfo entry = CoreGetEntry(id);239                if (entry != null)240                {241                    entry.SetStatus(status);242                    entry.SetEndTime(endTime);243                }244            }245            finally246            {247                System.Threading.Monitor.Exit(_syncRoot);248            }249        }250 251        /// <summary>252        /// Gets entry from buffer for given id. This id should be the253        /// id returned by Add method.254        /// </summary>255        /// <param name="id">Id of the entry to be fetched.</param>256        /// <returns>Entry corresponding to id if it is present else null257        /// </returns>258        internal HistoryInfo GetEntry(long id)259        {260            lock (_syncRoot)261            {262                ReallocateBufferIfNeeded();263 264                HistoryInfo entry = CoreGetEntry(id);265                if (entry != null)266                    if (!entry.Cleared)267                        return entry.Clone();268 269                return null;270            }271        }272 273        /// <summary>274        /// Get count HistoryEntries.275        /// </summary>276        /// <param name="id"></param>277        /// <param name="count"></param>278        /// <param name="newest"></param>279        /// <returns>History entries.</returns>280        internal HistoryInfo[] GetEntries(long id, long count, SwitchParameter newest)281        {282            ReallocateBufferIfNeeded();283 284            if (count < -1)285            {286                throw PSTraceSource.NewArgumentOutOfRangeException(nameof(count), count);287            }288 289            if (newest.ToString() == null)290            {291                throw PSTraceSource.NewArgumentNullException(nameof(newest));292            }293 294            if (count == -1 || count > _countEntriesAdded || count > _countEntriesInBuffer)295                count = _countEntriesInBuffer;296 297            if (count == 0 || _countEntriesInBuffer == 0)298            {299                return Array.Empty<HistoryInfo>();300            }301 302            lock (_syncRoot)303            {304                // Using list instead of an array to store the entries.With array we are getting null values305                // when the historybuffer size is changed306                List<HistoryInfo> entriesList = new List<HistoryInfo>();307                if (id > 0)308                {309                    long firstId, baseId;310                    baseId = id;311 312                    // get id,count,newest values313                    if (!newest.IsPresent)314                    {315                        // get older entries316 317                        // Calculate the first id (i.e lowest id to fetch)318                        firstId = baseId - count + 1;319 320                        // If first id is less than the lowest id in history store,321                        // assign lowest id as first ID322                        if (firstId < 1)323                        {324                            firstId = 1;325                        }326 327                        for (long i = baseId; i >= firstId; --i)328                        {329                            if (firstId <= 1) break;330                            // if entry is null , continue the loop with the next entry331                            if (_buffer[GetIndexFromId(i)] == null) continue;332                            if (_buffer[GetIndexFromId(i)].Cleared)333                            {334                                // we have to clear count entries before an id, so if an entry is null,decrement335                                // first id as long as its is greater than the lowest entry in the buffer.336                                firstId--;337                                continue;338                            }339                        }340 341                        for (long i = firstId; i <= baseId; ++i)342                        {343                            // if an entry is null after being cleared by clear-history cmdlet,344                            // continue with the next entry345                            if (_buffer[GetIndexFromId(i)] == null || _buffer[GetIndexFromId(i)].Cleared)346                                continue;347                            entriesList.Add(_buffer[GetIndexFromId(i)].Clone());348                        }349                    }350                    else351                    { // get latest entries352                        // first id becomes the id +count no of entries from the end of the buffer353                        firstId = baseId + count - 1;354                        // if first id is more than the no of entries in the buffer, first id will be the last entry in the buffer355                        if (firstId >= _countEntriesAdded)356                        {357                            firstId = _countEntriesAdded;358                        }359 360                        for (long i = baseId; i <= firstId; i++)361                        {362                            if (firstId >= _countEntriesAdded) break;363                            // if entry is null , continue the loop with the next entry364                            if (_buffer[GetIndexFromId(i)] == null) continue;365                            if (_buffer[GetIndexFromId(i)].Cleared)366                            {367                                // we have to clear count entries before an id, so if an entry is null,increment first id368                                firstId++;369                                continue;370                            }371                        }372 373                        for (long i = firstId; i >= baseId; --i)374                        {375                            // if an entry is null after being cleared by clear-history cmdlet,376                            // continue with the next entry377                            if (_buffer[GetIndexFromId(i)] == null || _buffer[GetIndexFromId(i)].Cleared)378                                continue;379                            entriesList.Add(_buffer[GetIndexFromId(i)].Clone());380                        }381                    }382                }383                else384                {385                    // get entries for count,newest386 387                    long index, SmallestID = 0;388                    // if we change the defaulthistory size and when no of entries exceed the size, then389                    // we need to get the smallest entry in the buffer when we want to clear the oldest entry390                    // eg if size is 5 and then the entries can be 7,6,1,2,3391                    if (_capacity != DefaultHistorySize)392                        SmallestID = SmallestIDinBuffer();393                    if (!newest.IsPresent)394                    {395                        // get oldest count entries396                        index = 1;397                        if (_capacity != DefaultHistorySize)398                        {399                            if (_countEntriesAdded > _capacity)400                                index = SmallestID;401                        }402 403                        for (long i = count - 1; i >= 0;)404                        {405                            if (index > _countEntriesAdded) break;406                            if ((index <= 0 || GetIndexFromId(index) >= _buffer.Length) ||407                                (_buffer[GetIndexFromId(index)].Cleared))408                            {409                                index++; continue;410                            }411                            else412                            {413                                entriesList.Add(_buffer[GetIndexFromId(index)].Clone());414                                i--; index++;415                            }416                        }417                    }418                    else419                    {420                        index = _countEntriesAdded; //SmallestIDinBuffer421 422                        for (long i = count - 1; i >= 0;)423                        {424                            // if an entry is cleared continue to the next entry425                            if (_capacity != DefaultHistorySize)426                            {427                                if (_countEntriesAdded > _capacity)428                                {429                                    if (index < SmallestID)430                                        break;431                                }432                            }433 434                            if (index < 1) break;435                            if ((index <= 0 || GetIndexFromId(index) >= _buffer.Length) ||436                                (_buffer[GetIndexFromId(index)].Cleared))437                            { index--; continue; }438                            else439                            {440                                // clone the entry from the history buffer441                                entriesList.Add(_buffer[GetIndexFromId(index)].Clone());442                                i--; index--;443                            }444                        }445                    }446                }447 448                HistoryInfo[] entries = new HistoryInfo[entriesList.Count];449                entriesList.CopyTo(entries);450                return entries;451            }452        }453 454        /// <summary>455        /// Get History Entries based on the WildCard Pattern value.456        /// If passed 0, returns all the values, else return on the basis of count.457        /// </summary>458        /// <param name="wildcardpattern"></param>459        /// <param name="count"></param>460        /// <param name="newest"></param>461        /// <returns></returns>462        internal HistoryInfo[] GetEntries(WildcardPattern wildcardpattern, long count, SwitchParameter newest)463        {464            lock (_syncRoot)465            {466                if (count < -1)467                {468                    throw PSTraceSource.NewArgumentOutOfRangeException(nameof(count), count);469                }470 471                if (newest.ToString() == null)472                {473                    throw PSTraceSource.NewArgumentNullException(nameof(newest));474                }475 476                if (count > _countEntriesAdded || count == -1)477                {478                    count = _countEntriesInBuffer;479                }480 481                List<HistoryInfo> cmdlist = new List<HistoryInfo>();482                long SmallestID = 1;483                // if buffersize is changes,Get the smallest entry that's not cleared in the buffer484                if (_capacity != DefaultHistorySize)485                    SmallestID = SmallestIDinBuffer();486                if (count != 0)487                {488                    if (!newest.IsPresent)489                    {490                        long id = 1;491                        if (_capacity != DefaultHistorySize)492                        {493                            if (_countEntriesAdded > _capacity)494                                id = SmallestID;495                        }496 497                        for (long i = 0; i <= count - 1;)498                        {499                            if (id > _countEntriesAdded) break;500                            if (!_buffer[GetIndexFromId(id)].Cleared && wildcardpattern.IsMatch(_buffer[GetIndexFromId(id)].CommandLine.Trim()))501                            {502                                cmdlist.Add(_buffer[GetIndexFromId(id)].Clone()); i++;503                            }504 505                            id++;506                        }507                    }508                    else509                    {510                        long id = _countEntriesAdded;511                        for (long i = 0; i <= count - 1;)512                        {513                            // if buffersize is changed,we have to loop from max entry to min entry that's not cleared514                            if (_capacity != DefaultHistorySize)515                            {516                                if (_countEntriesAdded > _capacity)517                                {518                                    if (id < SmallestID)519                                        break;520                                }521                            }522 523                            if (id < 1) break;524                            if (!_buffer[GetIndexFromId(id)].Cleared && wildcardpattern.IsMatch(_buffer[GetIndexFromId(id)].CommandLine.Trim()))525                            {526                                cmdlist.Add(_buffer[GetIndexFromId(id)].Clone()); i++;527                            }528 529                            id--;530                        }531                    }532                }533                else534                {535                    for (long i = 1; i <= _countEntriesAdded; i++)536                    {537                        if (!_buffer[GetIndexFromId(i)].Cleared && wildcardpattern.IsMatch(_buffer[GetIndexFromId(i)].CommandLine.Trim()))538                        {539                            cmdlist.Add(_buffer[GetIndexFromId(i)].Clone());540                        }541                    }542                }543 544                HistoryInfo[] entries = new HistoryInfo[cmdlist.Count];545                cmdlist.CopyTo(entries);546                return entries;547            }548        }549 550        /// <summary>551        /// Clears the history entry from buffer for a given id.552        /// </summary>553        /// <param name="id">Id of the entry to be Cleared.</param>554        /// <returns>Nothing.</returns>555        internal void ClearEntry(long id)556        {557            lock (_syncRoot)558            {559                if (id < 0)560                {561                    throw PSTraceSource.NewArgumentOutOfRangeException(nameof(id), id);562                }563                // no entries are present to clear564                if (_countEntriesInBuffer == 0)565                    return;566 567                // throw an exception if id is out of range568                if (id > _countEntriesAdded)569                {570                    return;571                }572 573                HistoryInfo entry = CoreGetEntry(id);574                if (entry != null)575                {576                    entry.Cleared = true;577                    _countEntriesInBuffer--;578                }579 580                return;581            }582        }583 584        /// <summary>585        /// gets the total number of entries added586        /// </summary>587        /// <returns>count of total entries added.</returns>588        internal int Buffercapacity()589        {590            return _capacity;591        }592 593        #endregion internal594 595        #region private596 597        /// <summary>598        /// Adds an entry to the buffer. If buffer is full, overwrites599        /// oldest entry in the buffer.600        /// </summary>601        /// <param name="entry"></param>602        /// <returns>Returns id for the entry. This id should be used to fetch603        /// the entry from the buffer.</returns>604        /// <remarks>Id starts from 1 and is incremented by 1 for each new entry</remarks>605        private long Add(HistoryInfo entry)606        {607            if (entry == null)608            {609                throw PSTraceSource.NewArgumentNullException(nameof(entry));610            }611 612            _buffer[GetIndexForNewEntry()] = entry;613 614            // Increment count of entries added so far615            _countEntriesAdded++;616 617            // Id of an entry in history is same as its number in history store.618            entry.SetId(_countEntriesAdded);619 620            // Increment count of entries in buffer by 1621            IncrementCountOfEntriesInBuffer();622 623            return _countEntriesAdded;624        }625 626        /// <summary>627        /// Gets entry from buffer for given id. This id should be the628        /// id returned by Add method.629        /// </summary>630        /// <param name="id">Id of the entry to be fetched.</param>631        /// <returns>Entry corresponding to id if it is present else null632        /// </returns>633        private HistoryInfo CoreGetEntry(long id)634        {635            if (id <= 0)636            {637                throw PSTraceSource.NewArgumentOutOfRangeException(nameof(id), id);638            }639 640            if (_countEntriesInBuffer == 0)641                return null;642            if (id > _countEntriesAdded)643            {644                return null;645            }646            // if (_buffer[GetIndexFromId(id)].Cleared == false )647            return _buffer[GetIndexFromId(id)];648            // else649            //    return null;650        }651 652        /// <summary>653        /// Gets the smallest id in the buffer.654        /// </summary>655        /// <returns></returns>656        private long SmallestIDinBuffer()657        {658            long minID = 0;659            if (_buffer == null)660                return minID;661            for (int i = 0; i < _buffer.Length; i++)662            {663                // assign the first entry in the buffer as min.664                if (_buffer[i] != null && !_buffer[i].Cleared)665                {666                    minID = _buffer[i].Id;667                    break;668                }669            }670            // check for the minimum id that is not cleared671            for (int i = 0; i < _buffer.Length; i++)672            {673                if (_buffer[i] != null && !_buffer[i].Cleared)674                    if (minID > _buffer[i].Id)675                        minID = _buffer[i].Id;676            }677 678            return minID;679        }680 681        /// <summary>682        /// Reallocates the buffer if history size changed.683        /// </summary>684        private void ReallocateBufferIfNeeded()685        {686            // Get current value of histoysize variable687            int historySize = GetHistorySize();688 689            if (historySize == _capacity)690                return;691 692            HistoryInfo[] tempBuffer = new HistoryInfo[historySize];693 694            // Calculate number of entries to copy in new buffer.695            int numberOfEntries = _countEntriesInBuffer;696 697            // when buffer size is changed,we have to consider the totalnumber of entries added698            if (numberOfEntries < _countEntriesAdded)699                numberOfEntries = (int)_countEntriesAdded;700 701            if (_countEntriesInBuffer > historySize)702                numberOfEntries = historySize;703 704            for (int i = numberOfEntries; i > 0; --i)705            {706                long nextId = _countEntriesAdded - i + 1;707 708                tempBuffer[GetIndexFromId(nextId, historySize)] = _buffer[GetIndexFromId(nextId)];709            }710 711            _countEntriesInBuffer = numberOfEntries;712            _capacity = historySize;713            _buffer = tempBuffer;714        }715 716        /// <summary>717        /// Get the index for new entry.718        /// </summary>719        /// <returns>Index for new entry.</returns>720        private int GetIndexForNewEntry()721        {722            return (int)(_countEntriesAdded % _capacity);723        }724 725        /// <summary>726        /// Gets index in buffer for an entry with given Id.727        /// </summary>728        /// <returns></returns>729        private int GetIndexFromId(long id)730        {731            return (int)((id - 1) % _capacity);732        }733 734        /// <summary>735        /// Gets index in buffer for an entry with given Id using passed in736        /// capacity.737        /// </summary>738        /// <param name="id"></param>739        /// <param name="capacity"></param>740        /// <returns></returns>741        private static int GetIndexFromId(long id, int capacity)742        {743            return (int)((id - 1) % capacity);744        }745 746        /// <summary>747        /// Increment number of entries in buffer by 1.748        /// </summary>749        private void IncrementCountOfEntriesInBuffer()750        {751            if (_countEntriesInBuffer < _capacity)752                _countEntriesInBuffer++;753        }754 755        /// <summary>756        /// Get the current history size.757        /// </summary>758        /// <returns></returns>759        private static int GetHistorySize()760        {761            int historySize = 0;762            var executionContext = LocalPipeline.GetExecutionContextFromTLS();763            object obj = executionContext?.GetVariableValue(SpecialVariables.HistorySizeVarPath);764            if (obj != null)765            {766                try767                {768                    historySize = (int)LanguagePrimitives.ConvertTo(obj, typeof(int), System.Globalization.CultureInfo.InvariantCulture);769                }770                catch (InvalidCastException)771                { }772            }773 774            if (historySize <= 0)775            {776                historySize = DefaultHistorySize;777            }778 779            return historySize;780        }781 782        /// <summary>783        /// Buffer.784        /// </summary>785        private HistoryInfo[] _buffer;786 787        /// <summary>788        /// Capacity of circular buffer.789        /// </summary>790        private int _capacity;791 792        /// <summary>793        /// Number of entries in buffer currently.794        /// </summary>795        private int _countEntriesInBuffer;796 797        /// <summary>798        /// Total number of entries added till now including those which have799        /// been overwritten after buffer got full. This is also number of800        /// last entry added.801        /// </summary>802        private long _countEntriesAdded;803 804        /// <summary>805        /// Private object for synchronization.806        /// </summary>807        private readonly object _syncRoot = new object();808 809        #endregion private810 811        /// <summary>812        /// Return the ID of the next history item to be added.813        /// </summary>814        internal long GetNextHistoryId()815        {816            return _countEntriesAdded + 1;817        }818 819        #region invoke_loop_detection820 821        /// <summary>822        /// This is a set of HistoryInfo ids which are currently being executed in the823        /// pipelines of the Runspace that is holding this 'History' instance.824        /// </summary>825        private readonly HashSet<long> _invokeHistoryIds = new HashSet<long>();826 827        internal bool PresentInInvokeHistoryEntrySet(HistoryInfo entry)828        {829            return _invokeHistoryIds.Contains(entry.Id);830        }831 832        internal void AddToInvokeHistoryEntrySet(HistoryInfo entry)833        {834            _invokeHistoryIds.Add(entry.Id);835        }836 837        internal void RemoveFromInvokeHistoryEntrySet(HistoryInfo entry)838        {839            _invokeHistoryIds.Remove(entry.Id);840        }841 842        #endregion invoke_loop_detection843    }844 845    /// <summary>846    /// This class Implements the get-history command.847    /// </summary>848    [Cmdlet(VerbsCommon.Get, "History", HelpUri = "https://go.microsoft.com/fwlink/?LinkID=2096788")]849    [OutputType(typeof(HistoryInfo))]850    public class GetHistoryCommand : PSCmdlet851    {852        /// <summary>853        /// Ids of entries to display.854        /// </summary>855        private long[] _id;856 857        /// <summary>858        /// Ids of entries to display.859        /// </summary>860        /// <value></value>861        [Parameter(Position = 0, ValueFromPipeline = true)]862        [ValidateRange((long)1, long.MaxValue)]863        public long[] Id864        {865            get866            {867                return _id;868            }869 870            set871            {872                _id = value;873            }874        }875 876        /// <summary>877        /// Is Count parameter specified.878        /// </summary>879        private bool _countParameterSpecified;880        /// <summary>881        /// Count of entries to display. By default, count is the length of the history buffer.882        /// So "Get-History" returns all history entries.883        /// </summary>884        private int _count;885 886        /// <summary>887        /// No of History Entries (starting from last) that are to be displayed.888        /// </summary>889        [Parameter(Position = 1)]890        [ValidateRange(0, (int)Int16.MaxValue)]891        public int Count892        {893            get894            {895                return _count;896            }897 898            set899            {900                _countParameterSpecified = true;901                _count = value;902            }903        }904 905        /// <summary>906        /// Implements the Processing() method for show/History command.907        /// </summary>908        protected override void ProcessRecord()909        {910            History history = ((LocalRunspace)Context.CurrentRunspace).History;911 912            if (_id != null)913            {914                if (!_countParameterSpecified)915                {916                    // If Id parameter is specified and count is not specified,917                    // get history918                    foreach (long id in _id)919                    {920                        Dbg.Assert(id > 0, "ValidateRangeAttribute should not allow this");921 922                        HistoryInfo entry = history.GetEntry(id);923 924                        if (entry != null && entry.Id == id)925                        {926                            WriteObject(entry);927                        }928                        else929                        {930                            Exception ex =931                                new ArgumentException932                                (933                                    StringUtil.Format(HistoryStrings.NoHistoryForId, id)934                                );935 936                            WriteError937                            (938                                new ErrorRecord939                                (940                                    ex,941                                    "GetHistoryNoHistoryForId",942                                    ErrorCategory.ObjectNotFound,943                                    id944                                )945                            );946                        }947                    }948                }949                else if (_id.Length > 1)950                {951                    Exception ex =952                        new ArgumentException953                        (954                            StringUtil.Format(HistoryStrings.NoCountWithMultipleIds)955                        );956 957                    ThrowTerminatingError958                    (959                        new ErrorRecord960                        (961                            ex,962                            "GetHistoryNoCountWithMultipleIds",963                            ErrorCategory.InvalidArgument,964                            _count965                        )966                    );967                }968                else969                {970                    long id = _id[0];971 972                    Dbg.Assert(id > 0, "ValidateRangeAttribute should not allow this");973                    WriteObject(history.GetEntries(id, _count, false), true);974                }975            }976            else977            {978                // The default value for _count is the size of the history buffer.979                if (!_countParameterSpecified)980                {981                    _count = history.Buffercapacity();982                }983 984                HistoryInfo[] entries = history.GetEntries(0, _count, true);985                for (long i = entries.Length - 1; i >= 0; i--)986                    WriteObject(entries[i]);987            }988        }989    }990 991    /// <summary>992    /// This class implements the Invoke-History command.993    /// </summary>994    [Cmdlet(VerbsLifecycle.Invoke, "History", SupportsShouldProcess = true, HelpUri = "https://go.microsoft.com/fwlink/?LinkID=2096586")]995    public class InvokeHistoryCommand : PSCmdlet996    {997        #region Parameters998 999        /// <summary>1000        /// Invoke cmd can execute only one history entry. If multiple1001        /// ids are provided, we throw error.1002        /// </summary>1003        private bool _multipleIdProvided;1004        private string _id;1005        /// <summary>1006        /// Accepts a string value indicating a previously executed command to1007        /// re-execute.1008        /// If string can be parsed to long,1009        /// it will be used as HistoryId1010        /// else1011        /// as a string value indicating a previously executed command to1012        /// re-execute. This string is the first n characters of the command1013        /// that is to be re-executed.1014        /// </summary>1015        [Parameter(Position = 0, ValueFromPipelineByPropertyName = true)]1016        public string Id1017        {1018            get1019            {1020                return _id;1021            }1022 1023            set1024            {1025                if (_id != null)1026                {1027                    // Id has been set already.1028                    _multipleIdProvided = true;1029                }1030 1031                _id = value;1032            }1033        }1034 1035        #endregion1036 1037        /// <summary>1038        /// Implements the BeginProcessing() method for eval/History command.1039        /// </summary>1040        protected override void EndProcessing()1041        {1042            // Invoke-history can execute only one command. If multiple1043            // ids were provided, throw exception1044            if (_multipleIdProvided)1045            {1046                ThrowTerminatingError(1047                    new ErrorRecord(1048                        new ArgumentException(HistoryStrings.InvokeHistoryMultipleCommandsError),1049                        "InvokeHistoryMultipleCommandsError",1050                        ErrorCategory.InvalidArgument,1051                        targetObject: null));1052            }1053 1054            var ctxRunspace = (LocalRunspace)Context.CurrentRunspace;1055            History history = ctxRunspace.History;1056            Dbg.Assert(history != null, "History should be non null");1057 1058            // Get the history entry to invoke1059            HistoryInfo entry = GetHistoryEntryToInvoke(history);1060            string commandToInvoke = entry.CommandLine;1061 1062            if (!ShouldProcess(commandToInvoke))1063            {1064                return;1065            }1066 1067            // Check if there is a loop in invoke-history1068            if (history.PresentInInvokeHistoryEntrySet(entry))1069            {1070                ThrowTerminatingError(1071                    new ErrorRecord(1072                        new InvalidOperationException(HistoryStrings.InvokeHistoryLoopDetected),1073                        "InvokeHistoryLoopDetected",1074                        ErrorCategory.InvalidOperation,1075                        targetObject: null));1076            }1077            else1078            {1079                history.AddToInvokeHistoryEntrySet(entry);1080            }1081 1082            // Replace Invoke-History with string which is getting invoked1083            ReplaceHistoryString(entry, ctxRunspace);1084 1085            try1086            {1087                // Echo command1088                Host.UI.WriteLine(commandToInvoke);1089            }1090            catch (HostException)1091            {1092                // when the host is not interactive, HostException is thrown1093                // do nothing1094            }1095 1096            // Items invoked as History should act as though they were submitted by the user - so should still come from1097            // the runspace itself. For this reason, it is insufficient to just use the InvokeScript method on the Cmdlet class.1098            using (System.Management.Automation.PowerShell ps = System.Management.Automation.PowerShell.Create(RunspaceMode.CurrentRunspace))1099            {1100                ps.AddScript(commandToInvoke);1101 1102                EventHandler<DataAddedEventArgs> debugAdded = (object sender, DataAddedEventArgs e) => { DebugRecord record = (DebugRecord)((PSDataCollection<DebugRecord>)sender)[e.Index]; WriteDebug(record.Message); };1103                EventHandler<DataAddedEventArgs> errorAdded = (object sender, DataAddedEventArgs e) => { ErrorRecord record = (ErrorRecord)((PSDataCollection<ErrorRecord>)sender)[e.Index]; WriteError(record); };1104                EventHandler<DataAddedEventArgs> informationAdded = (object sender, DataAddedEventArgs e) => { InformationRecord record = (InformationRecord)((PSDataCollection<InformationRecord>)sender)[e.Index]; WriteInformation(record); };1105                EventHandler<DataAddedEventArgs> progressAdded = (object sender, DataAddedEventArgs e) => { ProgressRecord record = (ProgressRecord)((PSDataCollection<ProgressRecord>)sender)[e.Index]; WriteProgress(record); };1106                EventHandler<DataAddedEventArgs> verboseAdded = (object sender, DataAddedEventArgs e) => { VerboseRecord record = (VerboseRecord)((PSDataCollection<VerboseRecord>)sender)[e.Index]; WriteVerbose(record.Message); };1107                EventHandler<DataAddedEventArgs> warningAdded = (object sender, DataAddedEventArgs e) => { WarningRecord record = (WarningRecord)((PSDataCollection<WarningRecord>)sender)[e.Index]; WriteWarning(record.Message); };1108 1109                ps.Streams.Debug.DataAdded += debugAdded;1110                ps.Streams.Error.DataAdded += errorAdded;1111                ps.Streams.Information.DataAdded += informationAdded;1112                ps.Streams.Progress.DataAdded += progressAdded;1113                ps.Streams.Verbose.DataAdded += verboseAdded;1114                ps.Streams.Warning.DataAdded += warningAdded;1115 1116                LocalRunspace localRunspace = ps.Runspace as LocalRunspace;1117 1118                try1119                {1120                    // Indicate to the system that we are in nested prompt mode, since we are emulating running the command at the prompt.1121                    // This ensures that the command being run as nested runs in the correct language mode, because CreatePipelineProcessor()1122                    // always forces CommandOrigin to Internal for nested running commands, and Command.CreateCommandProcessor() forces Internal1123                    // commands to always run in FullLanguage mode unless in a nested prompt.1124                    if (localRunspace != null)1125                    {1126                        localRunspace.InInternalNestedPrompt = ps.IsNested;1127                    }1128 1129                    Collection<PSObject> results = ps.Invoke();1130                    if (results.Count > 0)1131                    {1132                        WriteObject(results, true);1133                    }1134                }1135                finally1136                {1137                    history.RemoveFromInvokeHistoryEntrySet(entry);1138 1139                    if (localRunspace != null)1140                    {1141                        localRunspace.InInternalNestedPrompt = false;1142                    }1143 1144                    ps.Streams.Debug.DataAdded -= debugAdded;1145                    ps.Streams.Error.DataAdded -= errorAdded;1146                    ps.Streams.Information.DataAdded -= informationAdded;1147                    ps.Streams.Progress.DataAdded -= progressAdded;1148                    ps.Streams.Verbose.DataAdded -= verboseAdded;1149                    ps.Streams.Warning.DataAdded -= warningAdded;1150                }1151            }1152        }1153 1154        /// <summary>1155        /// Helper function which gets history entry to invoke.1156        /// </summary>1157        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly", Justification = "It's ok to use ID in the ArgumentException")]1158        private HistoryInfo GetHistoryEntryToInvoke(History history)1159        {1160            HistoryInfo entry = null;1161 1162            // User didn't specify any input parameter. Invoke the last1163            // entry1164            if (_id == null)1165            {1166                HistoryInfo[] entries = history.GetEntries(0, 1, true);1167 1168                if (entries.Length == 1)1169                {1170                    entry = entries[0];1171                }1172                else1173                {1174                    Exception ex =1175                        new InvalidOperationException1176                        (1177                            StringUtil.Format(HistoryStrings.NoLastHistoryEntryFound)1178                        );1179 1180                    ThrowTerminatingError1181                    (1182                        new ErrorRecord1183                        (1184                            ex,1185                            "InvokeHistoryNoLastHistoryEntryFound",1186                            ErrorCategory.InvalidOperation,1187                            null1188                        )1189                    );1190                }1191            }1192            else1193            {1194                // Parse input1195                PopulateIdAndCommandLine();1196                // User specified a commandline. Get list of all history entries1197                // and find latest match1198                if (_commandLine != null)1199                {1200                    HistoryInfo[] entries = history.GetEntries(0, -1, false);

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