diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/select-object.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/select-object.cs
index 4b31897411..aece2f1466 100644
--- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/select-object.cs
+++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/select-object.cs
@@ -161,7 +161,7 @@ namespace Microsoft.PowerShell.Commands
public SwitchParameter Wait { get; set; }
///
- /// Used to display the object at specified index.
+ /// Used to display the object at the specified index.
///
///
[Parameter(ParameterSetName = "IndexParameter")]
@@ -177,11 +177,36 @@ namespace Microsoft.PowerShell.Commands
{
_index = value;
_indexSpecified = true;
+ _isIncludeIndex = true;
Array.Sort(_index);
}
}
+
+ ///
+ /// Used to display all objects at the specified indices.
+ ///
+ ///
+ [Parameter(ParameterSetName = "SkipIndexParameter")]
+ [ValidateRangeAttribute(0, int.MaxValue)]
+ [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]
+ public int[] SkipIndex
+ {
+ get
+ {
+ return _index;
+ }
+ set
+ {
+ _index = value;
+ _indexSpecified = true;
+ _isIncludeIndex = false;
+ Array.Sort(_index);
+ }
+ }
+
private int[] _index;
private bool _indexSpecified;
+ private bool _isIncludeIndex;
#endregion
@@ -641,15 +666,18 @@ namespace Microsoft.PowerShell.Commands
_selectObjectQueue = new SelectObjectQueue(_first, _last, Skip, SkipLast, _firstOrLastSpecified);
}
- private int _indexOfCurrentObject = 0;
- private int _indexCount = 0;
///
+ /// Handles processing of InputObject.
///
protected override void ProcessRecord()
{
if (InputObject != AutomationNull.Value && InputObject != null)
{
- if (!_indexSpecified)
+ if (_indexSpecified)
+ {
+ ProcessIndexed();
+ }
+ else
{
_selectObjectQueue.Enqueue(InputObject);
PSObject streamingInputObject = _selectObjectQueue.StreamingDequeue();
@@ -657,39 +685,82 @@ namespace Microsoft.PowerShell.Commands
{
ProcessObjectAndHandleErrors(streamingInputObject);
}
+
if (_selectObjectQueue.AllRequestedObjectsProcessed && !this.Wait)
{
this.EndProcessing();
throw new StopUpstreamCommandsException(this);
}
}
- else
- {
- if (_indexOfCurrentObject < _index.Length)
- {
- int currentlyRequestedIndex = _index[_indexOfCurrentObject];
- if (_indexCount == currentlyRequestedIndex)
- {
- ProcessObjectAndHandleErrors(InputObject);
- while ((_indexOfCurrentObject < _index.Length) && (_index[_indexOfCurrentObject] == currentlyRequestedIndex))
- {
- _indexOfCurrentObject++;
- }
- }
- }
-
- if (!this.Wait && _indexOfCurrentObject >= _index.Length)
- {
- this.EndProcessing();
- throw new StopUpstreamCommandsException(this);
- }
-
- _indexCount++;
- }
}
}
///
+ /// The index of the active index filter.
+ ///
+ private int _currentFilterIndex;
+
+ ///
+ /// The index of the object being processed.
+ ///
+ private int _currentObjectIndex;
+
+ ///
+ /// Handles processing of InputObject if -Index or -SkipIndex is specified.
+ ///
+ private void ProcessIndexed()
+ {
+ if (_isIncludeIndex)
+ {
+ if (_currentFilterIndex < _index.Length)
+ {
+ int nextIndexToOutput = _index[_currentFilterIndex];
+ if (_currentObjectIndex == nextIndexToOutput)
+ {
+ ProcessObjectAndHandleErrors(InputObject);
+ while ((_currentFilterIndex < _index.Length) && (_index[_currentFilterIndex] == nextIndexToOutput))
+ {
+ _currentFilterIndex++;
+ }
+ }
+ }
+
+ if (!Wait && _currentFilterIndex >= _index.Length)
+ {
+ EndProcessing();
+ throw new StopUpstreamCommandsException(this);
+ }
+
+ _currentObjectIndex++;
+ }
+ else
+ {
+ if (_currentFilterIndex < _index.Length)
+ {
+ int nextIndexToSkip = _index[_currentFilterIndex];
+ if (_currentObjectIndex != nextIndexToSkip)
+ {
+ ProcessObjectAndHandleErrors(InputObject);
+ }
+ else
+ {
+ while ((_currentFilterIndex < _index.Length) && (_index[_currentFilterIndex] == nextIndexToSkip))
+ {
+ _currentFilterIndex++;
+ }
+ }
+ }
+ else
+ {
+ ProcessObjectAndHandleErrors(InputObject);
+ }
+
+ _currentObjectIndex++;
+ }
+ }
+
+ ///
+ /// Completes the processing of Input.
///
protected override void EndProcessing()
{
diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Select-Object.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Select-Object.Tests.ps1
index 8565b3ccae..872b785049 100644
--- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Select-Object.Tests.ps1
+++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Select-Object.Tests.ps1
@@ -244,6 +244,18 @@ Describe "Select-Object DRT basic functionality" -Tags "CI" {
$results[0] | Should -BeExactly "3"
}
+ It "Select-Object with SkipIndex should work" {
+ $results = "1", "2", "3" | Select-Object -SkipIndex 0, 2
+ $results | Should -HaveCount 1
+ $results[0] | Should -BeExactly "2"
+ }
+
+ It "Select-Object with SkipIndex should work with index out of range" {
+ $results = 0..10 | Select-Object -SkipIndex 5, 6, 7, 8, 11
+ $results | Should -HaveCount 7
+ $results -join ',' | Should -BeExactly "0,1,2,3,4,9,10"
+ }
+
It "Select-Object should handle dynamic (DLR) properties"{
$dynObj = [TestDynamic]::new()
$results = $dynObj, $dynObj | Select-Object -ExpandProperty FooProp