mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
Fix issue in Select-Object where Hashtable members (e.g., Keys) cannot be used with -Property or -ExpandProperty (#11097)
This commit is contained in:
+40
-23
@@ -5,6 +5,7 @@ using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Management.Automation;
|
||||
using System.Management.Automation.Internal;
|
||||
using System.Management.Automation.Language;
|
||||
@@ -159,27 +160,43 @@ namespace Microsoft.PowerShell.Commands
|
||||
|
||||
// If the object passed in is a hashtable, then turn it into a PSCustomObject so
|
||||
// that property expressions can work on it.
|
||||
target = IfHashtableWrapAsPSCustomObject(target);
|
||||
var wrappedTarget = IfHashtableWrapAsPSCustomObject(target, out bool wasHashtable);
|
||||
|
||||
// we have a string value
|
||||
IEnumerable<PSMemberInfo> members = null;
|
||||
IEnumerable<PSMemberInfo> members;
|
||||
if (HasWildCardCharacters)
|
||||
{
|
||||
// get the members first: this will expand the globbing on each parameter
|
||||
members = target.Members.Match(_stringValue,
|
||||
PSMemberTypes.Properties | PSMemberTypes.PropertySet | PSMemberTypes.Dynamic);
|
||||
members = wrappedTarget.Members.Match(
|
||||
_stringValue,
|
||||
PSMemberTypes.Properties | PSMemberTypes.PropertySet | PSMemberTypes.Dynamic);
|
||||
|
||||
// if target was a hashtable and no result is found from the keys, then use property value if available
|
||||
if (wasHashtable && !members.Any())
|
||||
{
|
||||
members = target.Members.Match(
|
||||
_stringValue,
|
||||
PSMemberTypes.Properties | PSMemberTypes.PropertySet | PSMemberTypes.Dynamic);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// we have no globbing: try an exact match, because this is quicker.
|
||||
PSMemberInfo x = target.Members[_stringValue];
|
||||
PSMemberInfo x = wrappedTarget.Members[_stringValue];
|
||||
|
||||
if ((x == null) && (target.BaseObject is System.Dynamic.IDynamicMetaObjectProvider))
|
||||
if (x == null)
|
||||
{
|
||||
// We could check if GetDynamicMemberNames includes the name... but
|
||||
// GetDynamicMemberNames is only a hint, not a contract, so we'd want
|
||||
// to attempt the binding whether it's in there or not.
|
||||
x = new PSDynamicMember(_stringValue);
|
||||
if (wasHashtable)
|
||||
{
|
||||
x = target.Members[_stringValue];
|
||||
}
|
||||
else if (wrappedTarget.BaseObject is System.Dynamic.IDynamicMetaObjectProvider)
|
||||
{
|
||||
// We could check if GetDynamicMemberNames includes the name... but
|
||||
// GetDynamicMemberNames is only a hint, not a contract, so we'd want
|
||||
// to attempt the binding whether it's in there or not.
|
||||
x = new PSDynamicMember(_stringValue);
|
||||
}
|
||||
}
|
||||
|
||||
List<PSMemberInfo> temp = new List<PSMemberInfo>();
|
||||
@@ -269,10 +286,6 @@ namespace Microsoft.PowerShell.Commands
|
||||
{
|
||||
List<PSPropertyExpressionResult> retVal = new List<PSPropertyExpressionResult>();
|
||||
|
||||
// If the object passed in is a hashtable, then turn it into a PSCustomObject so
|
||||
// that property expressions can work on it.
|
||||
target = IfHashtableWrapAsPSCustomObject(target);
|
||||
|
||||
// process the script case
|
||||
if (Script != null)
|
||||
{
|
||||
@@ -282,13 +295,10 @@ namespace Microsoft.PowerShell.Commands
|
||||
return retVal;
|
||||
}
|
||||
|
||||
// process the expression
|
||||
List<PSPropertyExpression> resolvedExpressionList = this.ResolveNames(target, expand);
|
||||
|
||||
foreach (PSPropertyExpression re in resolvedExpressionList)
|
||||
foreach (PSPropertyExpression resolvedName in ResolveNames(target, expand))
|
||||
{
|
||||
PSPropertyExpressionResult r = re.GetValue(target, eatExceptions);
|
||||
retVal.Add(r);
|
||||
PSPropertyExpressionResult result = resolvedName.GetValue(target, eatExceptions);
|
||||
retVal.Add(result);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
@@ -344,13 +354,21 @@ namespace Microsoft.PowerShell.Commands
|
||||
}
|
||||
}
|
||||
|
||||
private PSObject IfHashtableWrapAsPSCustomObject(PSObject target)
|
||||
private PSObject IfHashtableWrapAsPSCustomObject(PSObject target, out bool wrapped)
|
||||
{
|
||||
wrapped = false;
|
||||
|
||||
// If the object passed in is a hashtable, then turn it into a PSCustomObject so
|
||||
// that property expressions can work on it.
|
||||
if (PSObject.Base(target) is Hashtable targetAsHash)
|
||||
{
|
||||
target = (PSObject)(LanguagePrimitives.ConvertPSObjectToType(targetAsHash, typeof(PSObject), false, null, true));
|
||||
wrapped = true;
|
||||
return (PSObject)(LanguagePrimitives.ConvertPSObjectToType(
|
||||
targetAsHash,
|
||||
typeof(PSObject),
|
||||
recursion: false,
|
||||
formatProvider: null,
|
||||
ignoreUnknownMembers: true));
|
||||
}
|
||||
|
||||
return target;
|
||||
@@ -363,4 +381,3 @@ namespace Microsoft.PowerShell.Commands
|
||||
#endregion Private Members
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,249 +6,236 @@ Add-TestDynamicType
|
||||
|
||||
Describe "Select-Object" -Tags "CI" {
|
||||
BeforeEach {
|
||||
$dirObject = GetFileMock
|
||||
$TestLength = 3
|
||||
$dirObject = GetFileMock
|
||||
$TestLength = 3
|
||||
}
|
||||
|
||||
It "Handle piped input without error" {
|
||||
{ $dirObject | Select-Object } | Should -Not -Throw
|
||||
{ $dirObject | Select-Object } | Should -Not -Throw
|
||||
}
|
||||
|
||||
It "Should treat input as a single object with the inputObject parameter" {
|
||||
$result = $(Select-Object -InputObject $dirObject -Last $TestLength).Length
|
||||
$expected = $dirObject.Length
|
||||
|
||||
$result | Should -Be $expected
|
||||
$result = $(Select-Object -InputObject $dirObject -Last $TestLength).Length
|
||||
$expected = $dirObject.Length
|
||||
$result | Should -Be $expected
|
||||
}
|
||||
|
||||
It "Should be able to use the alias" {
|
||||
{ $dirObject | select } | Should -Not -Throw
|
||||
{ $dirObject | select } | Should -Not -Throw
|
||||
}
|
||||
|
||||
It "Should have same result when using alias" {
|
||||
$result = $dirObject | select
|
||||
$expected = $dirObject | Select-Object
|
||||
$result = $dirObject | Select-Object
|
||||
$expected = $dirObject | Select-Object
|
||||
|
||||
$result | Should -Be $expected
|
||||
$result | Should -Be $expected
|
||||
}
|
||||
|
||||
It "Should return correct object with First parameter" {
|
||||
$result = $dirObject | Select-Object -First $TestLength
|
||||
$result = $dirObject | Select-Object -First $TestLength
|
||||
|
||||
$result.Length | Should -Be $TestLength
|
||||
$result.Length | Should -Be $TestLength
|
||||
|
||||
for ($i=0; $i -lt $TestLength; $i++)
|
||||
{
|
||||
$result[$i].Name | Should -Be $dirObject[$i].Name
|
||||
}
|
||||
for ($i = 0; $i -lt $TestLength; $i++) {
|
||||
$result[$i].Name | Should -Be $dirObject[$i].Name
|
||||
}
|
||||
}
|
||||
|
||||
It "Should return correct object with Last parameter" {
|
||||
$result = $dirObject | Select-Object -Last $TestLength
|
||||
$result = $dirObject | Select-Object -Last $TestLength
|
||||
|
||||
$result.Length | Should -Be $TestLength
|
||||
$result.Length | Should -Be $TestLength
|
||||
|
||||
for ($i=0; $i -lt $TestLength; $i++)
|
||||
{
|
||||
$result[$i].Name | Should -Be $dirObject[$dirObject.Length - $TestLength + $i].Name
|
||||
}
|
||||
for ($i = 0; $i -lt $TestLength; $i++) {
|
||||
$result[$i].Name | Should -Be $dirObject[$dirObject.Length - $TestLength + $i].Name
|
||||
}
|
||||
}
|
||||
|
||||
It "Should work correctly with Unique parameter" {
|
||||
$result = ("a","b","c","a","a","a" | Select-Object -Unique).Length
|
||||
$expected = 3
|
||||
$result = ("a", "b", "c", "a", "a", "a" | Select-Object -Unique).Length
|
||||
$expected = 3
|
||||
|
||||
$result | Should -Be $expected
|
||||
$result | Should -Be $expected
|
||||
}
|
||||
|
||||
It "Should return correct object with Skip parameter" {
|
||||
$result = $dirObject | Select-Object -Skip $TestLength
|
||||
$result = $dirObject | Select-Object -Skip $TestLength
|
||||
|
||||
$result.Length | Should -Be ($dirObject.Length - $TestLength)
|
||||
$result.Length | Should -Be ($dirObject.Length - $TestLength)
|
||||
|
||||
for ($i=0; $i -lt $TestLength; $i++)
|
||||
{
|
||||
$result[$i].Name | Should -Be $dirObject[$TestLength + $i].Name
|
||||
}
|
||||
for ($i = 0; $i -lt $TestLength; $i++) {
|
||||
$result[$i].Name | Should -Be $dirObject[$TestLength + $i].Name
|
||||
}
|
||||
}
|
||||
|
||||
It "Should return an object with selected columns" {
|
||||
$result = $dirObject | Select-Object -Property Name, Size
|
||||
$result = $dirObject | Select-Object -Property Name, Size
|
||||
|
||||
$result.Length | Should -Be $dirObject.Length
|
||||
$result[0].Name | Should -Be $dirObject[0].Name
|
||||
$result[0].Size | Should -Be $dirObject[0].Size
|
||||
$result[0].Mode | Should -BeNullOrEmpty
|
||||
$result.Length | Should -Be $dirObject.Length
|
||||
$result[0].Name | Should -Be $dirObject[0].Name
|
||||
$result[0].Size | Should -Be $dirObject[0].Size
|
||||
$result[0].Mode | Should -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It "Should send output to pipe properly" {
|
||||
{$dirObject | Select-Object -Unique | pipelineConsume} | Should -Not -Throw
|
||||
{ $dirObject | Select-Object -Unique | pipelineConsume } | Should -Not -Throw
|
||||
}
|
||||
|
||||
It "Should select array indices with Index parameter" {
|
||||
$firstIndex = 2
|
||||
$secondIndex = 4
|
||||
$result = $dirObject | Select-Object -Index $firstIndex, $secondIndex
|
||||
$firstIndex = 2
|
||||
$secondIndex = 4
|
||||
$result = $dirObject | Select-Object -Index $firstIndex, $secondIndex
|
||||
|
||||
$result[0].Name | Should -Be $dirObject[$firstIndex].Name
|
||||
$result[1].Name | Should -Be $dirObject[$secondIndex].Name
|
||||
$result[0].Name | Should -Be $dirObject[$firstIndex].Name
|
||||
$result[1].Name | Should -Be $dirObject[$secondIndex].Name
|
||||
}
|
||||
|
||||
# Note that these two tests will modify original values of $dirObject
|
||||
|
||||
It "Should not wait when used without -Wait option" {
|
||||
$orig1 = $dirObject[0].Size
|
||||
$orig2 = $dirObject[$TestLength].Size
|
||||
$result = $dirObject | addOneToSizeProperty | Select-Object -First $TestLength
|
||||
$orig1 = $dirObject[0].Size
|
||||
$orig2 = $dirObject[$TestLength].Size
|
||||
$result = $dirObject | addOneToSizeProperty | Select-Object -First $TestLength
|
||||
|
||||
$result[0].Size | Should -Be ($orig1 + 1)
|
||||
$dirObject[0].Size | Should -Be ($orig1 + 1)
|
||||
$dirObject[$TestLength].Size | Should -Be $orig2
|
||||
$result[0].Size | Should -Be ($orig1 + 1)
|
||||
$dirObject[0].Size | Should -Be ($orig1 + 1)
|
||||
$dirObject[$TestLength].Size | Should -Be $orig2
|
||||
}
|
||||
|
||||
It "Should wait when used with -Wait option" {
|
||||
$orig1 = $dirObject[0].Size
|
||||
$orig2 = $dirObject[$TestLength].Size
|
||||
$result = $dirObject | addOneToSizeProperty | Select-Object -First $TestLength -Wait
|
||||
$orig1 = $dirObject[0].Size
|
||||
$orig2 = $dirObject[$TestLength].Size
|
||||
$result = $dirObject | addOneToSizeProperty | Select-Object -First $TestLength -Wait
|
||||
|
||||
$result[0].Size | Should -Be ($orig1 + 1)
|
||||
$dirObject[0].Size | Should -Be ($orig1 + 1)
|
||||
$dirObject[$TestLength].Size | Should -Be ($orig2 + 1)
|
||||
}
|
||||
$result[0].Size | Should -Be ($orig1 + 1)
|
||||
$dirObject[0].Size | Should -Be ($orig1 + 1)
|
||||
$dirObject[$TestLength].Size | Should -Be ($orig2 + 1)
|
||||
}
|
||||
|
||||
It "Should not leak 'StopUpstreamCommandsException' internal exception for stopping upstream" {
|
||||
1,2 | Select-Object -First 1 -ErrorVariable err
|
||||
$err | Should -BeNullOrEmpty
|
||||
}
|
||||
It "Should not leak 'StopUpstreamCommandsException' internal exception for stopping upstream" {
|
||||
1, 2 | Select-Object -First 1 -ErrorVariable err
|
||||
$err | Should -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Describe "Select-Object DRT basic functionality" -Tags "CI" {
|
||||
BeforeAll {
|
||||
$employees = [pscustomobject]@{"FirstName"="joseph"; "LastName"="smith"; "YearsInMS"=15},
|
||||
[pscustomobject]@{"FirstName"="paul"; "LastName"="smith"; "YearsInMS"=15},
|
||||
[pscustomobject]@{"FirstName"="mary"; "LastName"="soe"; "YearsInMS"=5},
|
||||
[pscustomobject]@{"FirstName"="edmund"; "LastName"="bush"; "YearsInMS"=9}
|
||||
}
|
||||
BeforeAll {
|
||||
$employees = @(
|
||||
[pscustomobject]@{"FirstName" = "joseph"; "LastName" = "smith"; "YearsInMS" = 15 }
|
||||
[pscustomobject]@{"FirstName" = "paul"; "LastName" = "smith"; "YearsInMS" = 15 }
|
||||
[pscustomobject]@{"FirstName" = "mary"; "LastName" = "soe"; "YearsInMS" = 5 }
|
||||
[pscustomobject]@{"FirstName" = "edmund"; "LastName" = "bush"; "YearsInMS" = 9 }
|
||||
)
|
||||
}
|
||||
|
||||
It "Select-Object with empty script block property should throw"{
|
||||
$e = { "bar" | Select-Object -Prop {} -ErrorAction Stop } |
|
||||
Should -Throw -ErrorId "EmptyScriptBlockAndNoName,Microsoft.PowerShell.Commands.SelectObjectCommand" -PassThru
|
||||
$e.CategoryInfo | Should -Match "PSArgumentException"
|
||||
}
|
||||
It "Select-Object with empty script block property should throw" {
|
||||
$e = { "bar" | Select-Object -Prop {} -ErrorAction Stop } |
|
||||
Should -Throw -ErrorId "EmptyScriptBlockAndNoName,Microsoft.PowerShell.Commands.SelectObjectCommand" -PassThru
|
||||
$e.CategoryInfo | Should -Match "PSArgumentException"
|
||||
}
|
||||
|
||||
It "Select-Object with string property should work"{
|
||||
$result = "bar" | Select-Object -Prop foo | Measure-Object
|
||||
$result.Count | Should -Be 1
|
||||
}
|
||||
It "Select-Object with Property First Last Overlap should work" {
|
||||
$results = $employees | Select-Object -Property "YearsInMS", "L*" -First 2 -Last 3
|
||||
$results.Count | Should -Be 4
|
||||
}
|
||||
|
||||
It "Select-Object with Property First Last Overlap should work"{
|
||||
$results = $employees | Select-Object -Property "YearsInMS", "L*" -First 2 -Last 3
|
||||
It "Select-Object with string property should work" {
|
||||
$result = "bar" | Select-Object -Prop foo | Measure-Object
|
||||
$result.Count | Should -Be 1
|
||||
}
|
||||
|
||||
$results.Count | Should -Be 4
|
||||
It "Select-Object with Property First Last should work" {
|
||||
$results = $employees | Select-Object -Property "YearsInMS", "L*" -First 2 -Last 1
|
||||
|
||||
$results[0].LastName | Should -Be $employees[0].LastName
|
||||
$results[1].LastName | Should -Be $employees[1].LastName
|
||||
$results[2].LastName | Should -Be $employees[2].LastName
|
||||
$results[3].LastName | Should -Be $employees[3].LastName
|
||||
$results.Count | Should -Be 3
|
||||
|
||||
$results[0].YearsInMS | Should -Be $employees[0].YearsInMS
|
||||
$results[1].YearsInMS | Should -Be $employees[1].YearsInMS
|
||||
$results[2].YearsInMS | Should -Be $employees[2].YearsInMS
|
||||
$results[3].YearsInMS | Should -Be $employees[3].YearsInMS
|
||||
}
|
||||
$results[0].LastName | Should -Be $employees[0].LastName
|
||||
$results[1].LastName | Should -Be $employees[1].LastName
|
||||
$results[2].LastName | Should -Be $employees[3].LastName
|
||||
|
||||
It "Select-Object with Property First Last should work"{
|
||||
$results = $employees | Select-Object -Property "YearsInMS", "L*" -First 2 -Last 1
|
||||
$results[0].YearsInMS | Should -Be $employees[0].YearsInMS
|
||||
$results[1].YearsInMS | Should -Be $employees[1].YearsInMS
|
||||
$results[2].YearsInMS | Should -Be $employees[3].YearsInMS
|
||||
}
|
||||
|
||||
$results.Count | Should -Be 3
|
||||
It "Select-Object with Property First should work" {
|
||||
$results = $employees | Select-Object -Property "YearsInMS", "L*" -First 2
|
||||
|
||||
$results[0].LastName | Should -Be $employees[0].LastName
|
||||
$results[1].LastName | Should -Be $employees[1].LastName
|
||||
$results[2].LastName | Should -Be $employees[3].LastName
|
||||
$results.Count | Should -Be 2
|
||||
|
||||
$results[0].YearsInMS | Should -Be $employees[0].YearsInMS
|
||||
$results[1].YearsInMS | Should -Be $employees[1].YearsInMS
|
||||
$results[2].YearsInMS | Should -Be $employees[3].YearsInMS
|
||||
}
|
||||
$results[0].LastName | Should -Be $employees[0].LastName
|
||||
$results[1].LastName | Should -Be $employees[1].LastName
|
||||
|
||||
It "Select-Object with Property First should work"{
|
||||
$results = $employees | Select-Object -Property "YearsInMS", "L*" -First 2
|
||||
$results[0].YearsInMS | Should -Be $employees[0].YearsInMS
|
||||
$results[1].YearsInMS | Should -Be $employees[1].YearsInMS
|
||||
}
|
||||
|
||||
$results.Count | Should -Be 2
|
||||
It "Select-Object with Property First Zero should work" {
|
||||
$results = $employees | Select-Object -Property "YearsInMS", "L*" -First 0
|
||||
|
||||
$results[0].LastName | Should -Be $employees[0].LastName
|
||||
$results[1].LastName | Should -Be $employees[1].LastName
|
||||
$results.Count | Should -Be 0
|
||||
}
|
||||
|
||||
$results[0].YearsInMS | Should -Be $employees[0].YearsInMS
|
||||
$results[1].YearsInMS | Should -Be $employees[1].YearsInMS
|
||||
}
|
||||
It "Select-Object with Property Last Zero should work" {
|
||||
$results = $employees | Select-Object -Property "YearsInMS", "L*" -Last 0
|
||||
|
||||
It "Select-Object with Property First Zero should work"{
|
||||
$results = $employees | Select-Object -Property "YearsInMS", "L*" -First 0
|
||||
$results.Count | Should -Be 0
|
||||
}
|
||||
|
||||
$results.Count | Should -Be 0
|
||||
}
|
||||
It "Select-Object with Unique should work" {
|
||||
$results = $employees | Select-Object -Property "YearsInMS", "L*" -Unique:$true
|
||||
|
||||
It "Select-Object with Property Last Zero should work"{
|
||||
$results = $employees | Select-Object -Property "YearsInMS", "L*" -Last 0
|
||||
$results.Count | Should -Be 3
|
||||
|
||||
$results.Count | Should -Be 0
|
||||
}
|
||||
$results[0].LastName | Should -Be $employees[1].LastName
|
||||
$results[1].LastName | Should -Be $employees[2].LastName
|
||||
$results[2].LastName | Should -Be $employees[3].LastName
|
||||
|
||||
It "Select-Object with Unique should work"{
|
||||
$results = $employees | Select-Object -Property "YearsInMS", "L*" -Unique:$true
|
||||
$results[0].YearsInMS | Should -Be $employees[1].YearsInMS
|
||||
$results[1].YearsInMS | Should -Be $employees[2].YearsInMS
|
||||
$results[2].YearsInMS | Should -Be $employees[3].YearsInMS
|
||||
}
|
||||
|
||||
$results.Count | Should -Be 3
|
||||
It "Select-Object with Simple should work" {
|
||||
$employee1 = [pscustomobject]@{"FirstName" = "joesph"; "LastName" = "smith"; "YearsInMS" = 15 }
|
||||
$employee2 = [pscustomobject]@{"FirstName" = "paul"; "LastName" = "smith"; "YearsInMS" = 15 }
|
||||
$employee3 = [pscustomobject]@{"FirstName" = "mary"; "LastName" = "soe"; "YearsInMS" = 15 }
|
||||
$employees3 = @($employee1, $employee2, $employee3, $employee4)
|
||||
$results = $employees3 | Select-Object -Property "FirstName", "YearsInMS"
|
||||
|
||||
$results[0].LastName | Should -Be $employees[1].LastName
|
||||
$results[1].LastName | Should -Be $employees[2].LastName
|
||||
$results[2].LastName | Should -Be $employees[3].LastName
|
||||
$results.Count | Should -Be 3
|
||||
|
||||
$results[0].YearsInMS | Should -Be $employees[1].YearsInMS
|
||||
$results[1].YearsInMS | Should -Be $employees[2].YearsInMS
|
||||
$results[2].YearsInMS | Should -Be $employees[3].YearsInMS
|
||||
}
|
||||
$results[0].FirstName | Should -Be $employees3[0].FirstName
|
||||
$results[1].FirstName | Should -Be $employees3[1].FirstName
|
||||
$results[2].FirstName | Should -Be $employees3[2].FirstName
|
||||
|
||||
It "Select-Object with Simple should work"{
|
||||
$employee1 = [pscustomobject]@{"FirstName"="joesph"; "LastName"="smith"; "YearsInMS"=15}
|
||||
$employee2 = [pscustomobject]@{"FirstName"="paul"; "LastName"="smith"; "YearsInMS"=15}
|
||||
$employee3 = [pscustomobject]@{"FirstName"="mary"; "LastName"="soe"; "YearsInMS"=15}
|
||||
$employees3 = @($employee1,$employee2,$employee3,$employee4)
|
||||
$results = $employees3 | Select-Object -Property "FirstName", "YearsInMS"
|
||||
$results[0].YearsInMS | Should -Be $employees3[0].YearsInMS
|
||||
$results[1].YearsInMS | Should -Be $employees3[1].YearsInMS
|
||||
$results[2].YearsInMS | Should -Be $employees3[2].YearsInMS
|
||||
}
|
||||
|
||||
$results.Count | Should -Be 3
|
||||
It "Select-Object with no input should work" {
|
||||
$results = $null | Select-Object -Property "FirstName", "YearsInMS", "FirstNa*"
|
||||
$results.Count | Should -Be 0
|
||||
}
|
||||
|
||||
$results[0].FirstName | Should -Be $employees3[0].FirstName
|
||||
$results[1].FirstName | Should -Be $employees3[1].FirstName
|
||||
$results[2].FirstName | Should -Be $employees3[2].FirstName
|
||||
It "Select-Object with Start-Time In Idle Process should work" {
|
||||
$results = Get-Process * | Select-Object ProcessName
|
||||
$results.Count | Should -Not -Be 0
|
||||
}
|
||||
|
||||
$results[0].YearsInMS | Should -Be $employees3[0].YearsInMS
|
||||
$results[1].YearsInMS | Should -Be $employees3[1].YearsInMS
|
||||
$results[2].YearsInMS | Should -Be $employees3[2].YearsInMS
|
||||
}
|
||||
It "Select-Object with Skip should work" {
|
||||
$results = "1", "2", "3" | Select-Object -Skip 1
|
||||
$results.Count | Should -Be 2
|
||||
$results[0] | Should -Be 2
|
||||
$results[1] | Should -Be 3
|
||||
}
|
||||
|
||||
It "Select-Object with no input should work"{
|
||||
$results = $null | Select-Object -Property "FirstName", "YearsInMS", "FirstNa*"
|
||||
$results.Count | Should -Be 0
|
||||
}
|
||||
|
||||
It "Select-Object with Start-Time In Idle Process should work" {
|
||||
$results = Get-Process * | Select-Object ProcessName
|
||||
$results.Count | Should -Not -Be 0
|
||||
}
|
||||
|
||||
It "Select-Object with Skip should work"{
|
||||
$results = "1","2","3" | Select-Object -Skip 1
|
||||
$results.Count | Should -Be 2
|
||||
$results[0] | Should -Be 2
|
||||
$results[1] | Should -Be 3
|
||||
}
|
||||
|
||||
It "Select-Object with Index should work"{
|
||||
$results = "1","2","3" | Select-Object -Index 2
|
||||
$results.Count | Should -Be 1
|
||||
$results[0] | Should -BeExactly "3"
|
||||
}
|
||||
It "Select-Object with Index should work" {
|
||||
$results = "1", "2", "3" | Select-Object -Index 2
|
||||
$results.Count | Should -Be 1
|
||||
$results[0] | Should -BeExactly "3"
|
||||
}
|
||||
|
||||
It "Select-Object with SkipIndex should work" {
|
||||
$results = "1", "2", "3" | Select-Object -SkipIndex 0, 2
|
||||
@@ -262,7 +249,7 @@ Describe "Select-Object DRT basic functionality" -Tags "CI" {
|
||||
$results -join ',' | Should -BeExactly "0,1,2,3,4,9,10"
|
||||
}
|
||||
|
||||
It "Select-Object should handle dynamic (DLR) properties"{
|
||||
It "Select-Object should handle dynamic (DLR) properties" {
|
||||
$dynObj = [TestDynamic]::new()
|
||||
$results = $dynObj, $dynObj | Select-Object -ExpandProperty FooProp
|
||||
$results.Count | Should -Be 2
|
||||
@@ -270,7 +257,7 @@ Describe "Select-Object DRT basic functionality" -Tags "CI" {
|
||||
$results[1] | Should -Be 123
|
||||
}
|
||||
|
||||
It "Select-Object should handle dynamic (DLR) properties without GetDynamicMemberNames hint"{
|
||||
It "Select-Object should handle dynamic (DLR) properties without GetDynamicMemberNames hint" {
|
||||
$dynObj = [TestDynamic]::new()
|
||||
$results = $dynObj, $dynObj | Select-Object -ExpandProperty HiddenProp
|
||||
$results.Count | Should -Be 2
|
||||
@@ -278,7 +265,7 @@ Describe "Select-Object DRT basic functionality" -Tags "CI" {
|
||||
$results[1] | Should -Be 789
|
||||
}
|
||||
|
||||
It "Select-Object should handle wildcarded dynamic (DLR) properties when hinted by GetDynamicMemberNames"{
|
||||
It "Select-Object should handle wildcarded dynamic (DLR) properties when hinted by GetDynamicMemberNames" {
|
||||
$dynObj = [TestDynamic]::new()
|
||||
$results = $dynObj, $dynObj | Select-Object -ExpandProperty FooP*
|
||||
$results.Count | Should -Be 2
|
||||
@@ -286,7 +273,7 @@ Describe "Select-Object DRT basic functionality" -Tags "CI" {
|
||||
$results[1] | Should -Be 123
|
||||
}
|
||||
|
||||
It "Select-Object should work when multiple dynamic (DLR) properties match"{
|
||||
It "Select-Object should work when multiple dynamic (DLR) properties match" {
|
||||
$dynObj = [TestDynamic]::new()
|
||||
$results = $dynObj, $dynObj | Select-Object *Prop
|
||||
$results.Count | Should -Be 2
|
||||
@@ -296,9 +283,9 @@ Describe "Select-Object DRT basic functionality" -Tags "CI" {
|
||||
$results[1].BarProp | Should -Be 456
|
||||
}
|
||||
|
||||
It "Select-Object -ExpandProperty should yield errors if multiple dynamic (DLR) properties match"{
|
||||
It "Select-Object -ExpandProperty should yield errors if multiple dynamic (DLR) properties match" {
|
||||
$dynObj = [TestDynamic]::new()
|
||||
$e = { $results = $dynObj, $dynObj | Select-Object -ExpandProperty *Prop -ErrorAction Stop} |
|
||||
$e = { $results = $dynObj, $dynObj | Select-Object -ExpandProperty *Prop -ErrorAction Stop } |
|
||||
Should -Throw -PassThru -ErrorId "MutlipleExpandProperties,Microsoft.PowerShell.Commands.SelectObjectCommand"
|
||||
$e.CategoryInfo | Should -Match "PSArgumentException"
|
||||
}
|
||||
@@ -306,49 +293,49 @@ Describe "Select-Object DRT basic functionality" -Tags "CI" {
|
||||
|
||||
Describe "Select-Object with Property = '*'" -Tags "CI" {
|
||||
|
||||
# Issue #2420
|
||||
It "Select-Object with implicit Property = '*' don't return property named '*'"{
|
||||
$results = [pscustomobject]@{Thing="thing1"} | Select-Object -ExcludeProperty thing
|
||||
$results.psobject.Properties.Item("*") | Should -BeNullOrEmpty
|
||||
}
|
||||
# Issue #2420
|
||||
It "Select-Object with implicit Property = '*' don't return property named '*'" {
|
||||
$results = [pscustomobject]@{Thing = "thing1" } | Select-Object -ExcludeProperty thing
|
||||
$results.psobject.Properties.Item("*") | Should -BeNullOrEmpty
|
||||
}
|
||||
|
||||
# Issue #2420
|
||||
It "Select-Object with explicit Property = '*' don't return property named '*'"{
|
||||
$results = [pscustomobject]@{Thing="thing1"} | Select-Object -Property * -ExcludeProperty thing
|
||||
$results.psobject.Properties.Item("*") | Should -BeNullOrEmpty
|
||||
}
|
||||
# Issue #2420
|
||||
It "Select-Object with explicit Property = '*' don't return property named '*'" {
|
||||
$results = [pscustomobject]@{Thing = "thing1" } | Select-Object -Property * -ExcludeProperty thing
|
||||
$results.psobject.Properties.Item("*") | Should -BeNullOrEmpty
|
||||
}
|
||||
|
||||
# Issue #2351
|
||||
It "Select-Object with implicit Property = '*' exclude single property"{
|
||||
$results = [pscustomobject]@{Thing="thing1"} | Select-Object -ExcludeProperty thing
|
||||
$results.psobject.Properties.Item("Thing") | Should -BeNullOrEmpty
|
||||
$results.psobject.Properties.Item("*") | Should -BeNullOrEmpty
|
||||
}
|
||||
# Issue #2351
|
||||
It "Select-Object with implicit Property = '*' exclude single property" {
|
||||
$results = [pscustomobject]@{Thing = "thing1" } | Select-Object -ExcludeProperty thing
|
||||
$results.psobject.Properties.Item("Thing") | Should -BeNullOrEmpty
|
||||
$results.psobject.Properties.Item("*") | Should -BeNullOrEmpty
|
||||
}
|
||||
|
||||
# Issue #2351
|
||||
It "Select-Object with explicit Property = '*' exclude single property"{
|
||||
$results = [pscustomobject]@{Thing="thing1"} | Select-Object -Property * -ExcludeProperty thing
|
||||
$results.psobject.Properties.Item("Thing") | Should -BeNullOrEmpty
|
||||
$results.psobject.Properties.Item("*") | Should -BeNullOrEmpty
|
||||
}
|
||||
# Issue #2351
|
||||
It "Select-Object with explicit Property = '*' exclude single property" {
|
||||
$results = [pscustomobject]@{Thing = "thing1" } | Select-Object -Property * -ExcludeProperty thing
|
||||
$results.psobject.Properties.Item("Thing") | Should -BeNullOrEmpty
|
||||
$results.psobject.Properties.Item("*") | Should -BeNullOrEmpty
|
||||
}
|
||||
|
||||
# Issue #2351
|
||||
It "Select-Object with implicit Property = '*' exclude not single property"{
|
||||
$results = [pscustomobject]@{Thing="thing1";Param2="param2"} | Select-Object -ExcludeProperty Param2
|
||||
$results.Param2 | Should -BeNullOrEmpty
|
||||
$results.Thing | Should -BeExactly "thing1"
|
||||
}
|
||||
# Issue #2351
|
||||
It "Select-Object with implicit Property = '*' exclude not single property" {
|
||||
$results = [pscustomobject]@{Thing = "thing1"; Param2 = "param2" } | Select-Object -ExcludeProperty Param2
|
||||
$results.Param2 | Should -BeNullOrEmpty
|
||||
$results.Thing | Should -BeExactly "thing1"
|
||||
}
|
||||
|
||||
# Issue #2351
|
||||
It "Select-Object with explicit Property = '*' exclude not single property"{
|
||||
$results = [pscustomobject]@{Thing="thing1";Param2="param2"} | Select-Object -Property * -ExcludeProperty Param2
|
||||
$results.Param2 | Should -BeNullOrEmpty
|
||||
$results.Thing | Should -BeExactly "thing1"
|
||||
}
|
||||
# Issue #2351
|
||||
It "Select-Object with explicit Property = '*' exclude not single property" {
|
||||
$results = [pscustomobject]@{Thing = "thing1"; Param2 = "param2" } | Select-Object -Property * -ExcludeProperty Param2
|
||||
$results.Param2 | Should -BeNullOrEmpty
|
||||
$results.Thing | Should -BeExactly "thing1"
|
||||
}
|
||||
|
||||
It "Select-Object with ExpandProperty and Property don't skip processing ExcludeProperty" {
|
||||
$p = Get-Process -Id $PID | Select-Object -Property Process* -ExcludeProperty ProcessorAffinity -ExpandProperty Modules
|
||||
$p[0].psobject.Properties.Item("ProcessorAffinity") | Should -BeNullOrEmpty
|
||||
$p = Get-Process -Id $PID | Select-Object -Property Process* -ExcludeProperty ProcessorAffinity -ExpandProperty Modules
|
||||
$p[0].psobject.Properties.Item("ProcessorAffinity") | Should -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It "Select-Object add 'Selected.*' type only once" {
|
||||
@@ -363,12 +350,45 @@ Describe "Select-Object with Property = '*'" -Tags "CI" {
|
||||
$obj.psobject.TypeNames[0] | Should -BeLike "Selected*"
|
||||
$obj.psobject.TypeNames[1] | Should -Not -BeLike "Selected*"
|
||||
$obj.psobject.TypeNames[2] | Should -Not -BeLike "Selected*"
|
||||
}
|
||||
}
|
||||
|
||||
$obj = $obj | Select-Object
|
||||
Describe 'Select-Object behaviour with hashtable entries and actual members' -Tags CI {
|
||||
|
||||
$obj.psobject.TypeNames.Count | Should -Be 3
|
||||
$obj.psobject.TypeNames[0] | Should -BeLike "Selected*"
|
||||
$obj.psobject.TypeNames[1] | Should -Not -BeLike "Selected*"
|
||||
$obj.psobject.TypeNames[2] | Should -Not -BeLike "Selected*"
|
||||
It 'can retrieve a hashtable entry as a property' {
|
||||
$hashtable = @{ Entry = 100 }
|
||||
|
||||
$result = $hashtable | Select-Object -Property Entry
|
||||
$result.Entry | Should -Be 100
|
||||
|
||||
$hashtable |
|
||||
Select-Object -ExpandProperty Entry |
|
||||
Should -Be 100
|
||||
}
|
||||
|
||||
It 'can retrieve true hashtable members' {
|
||||
$hashtable = @{ Value = 10 }
|
||||
$result = $hashtable | Select-Object -Property Keys
|
||||
$result.Keys | Should -Be 'Value'
|
||||
|
||||
$hashtable |
|
||||
Select-Object -ExpandProperty Keys |
|
||||
Should -Be 'Value'
|
||||
}
|
||||
|
||||
It 'should prioritise hashtable entries where available' {
|
||||
$hashtable = @{ Keys = 10 }
|
||||
$result = $hashtable | Select-Object -Property Keys
|
||||
$result.Keys | Should -Be 10
|
||||
|
||||
$hashtable | Select-Object -ExpandProperty Keys | Should -Be 10
|
||||
}
|
||||
|
||||
It 'should get the hashtable Count member' {
|
||||
$hashtable = @{ a = 10; b = 20; c = 30 }
|
||||
$result = $hashtable | Select-Object -Property Count
|
||||
$result.Count | Should -Be 3
|
||||
|
||||
$hashtable | Select-Object -ExpandProperty Count | Should -Be 3
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user