Skip to content

Prefer literal Select-Object property matches#27515

Open
KirtiRamchandani wants to merge 2 commits into
PowerShell:masterfrom
KirtiRamchandani:fix/select-object-literal-wildcards
Open

Prefer literal Select-Object property matches#27515
KirtiRamchandani wants to merge 2 commits into
PowerShell:masterfrom
KirtiRamchandani:fix/select-object-literal-wildcards

Conversation

@KirtiRamchandani
Copy link
Copy Markdown

@KirtiRamchandani KirtiRamchandani commented May 24, 2026

PR Summary

Makes Select-Object prefer an exact property-name match before treating wildcard-looking property arguments as wildcard patterns.

PR Context

Fix #25982.

The cmdlet currently treats property names containing wildcard characters only as wildcard patterns, even when the input object has a property whose literal name matches the requested value. This means a generated object with a property such as Foo[] cannot reliably select or expand that property even when the caller uses [WildcardPattern]::Escape().

This change checks for a literal property match first, using the wildcard-unescaped property expression where applicable. If no exact property exists, existing wildcard expansion behavior is preserved.

Regression tests cover:

  • escaped literal property names such as Foo[]
  • exact property names such as Foo* taking precedence over wildcard expansion
  • -ExpandProperty with escaped literal property names

PR Checklist

  • PR has a meaningful title
  • Summarized changes
  • This PR is focused on one issue
  • Make sure all .h, .cpp, .cs, .ps1 and .psm1 files have the correct copyright header
  • This PR is ready to merge and is not work-in-progress
  • Breaking change: No
  • User-facing change: Not required
  • Tests added/updated

Validation

  • Start-PSBuild -NoPSModuleRestore -CI -SkipExperimentalFeatureGeneration -UseNuGetOrg
  • Direct repro with [WildcardPattern]::Escape('Foo[]') succeeds for both -Property and -ExpandProperty.
  • Start-PSPester -Path test/powershell/Modules/Microsoft.PowerShell.Utility/Select-Object.Tests.ps1 -UseNuGetOrg -ThrowOnFailure -Terse -SkipTestToolBuild

Result: Select-Object.Tests.ps1 passed: 54 passed, 0 failed.

Copilot AI review requested due to automatic review settings May 24, 2026 14:05
@KirtiRamchandani KirtiRamchandani requested a review from a team as a code owner May 24, 2026 14:05
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR updates Select-Object to correctly handle literal property names that include wildcard characters, and adds Pester tests covering the new resolution behavior.

Changes:

  • Prefer exact (literal) property-name matches before performing wildcard expansion for -Property.
  • Apply the same literal-name handling to -ExpandProperty.
  • Add tests covering escaped wildcard characters and exact-match precedence.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
test/powershell/Modules/Microsoft.PowerShell.Utility/Select-Object.Tests.ps1 Adds test coverage for literal property names containing wildcard characters and exact-match precedence.
src/Microsoft.PowerShell.Commands.Utility/commands/utility/Select-Object.cs Changes property resolution to detect and select exact property names (including wildcard characters) before wildcard expansion.

Comment on lines +573 to +575
return inputObject.Properties[propertyName] is null
? null
: new PSPropertyExpression(propertyName, isResolved: true);
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 2ce27ae3d: literal escaped property resolution now looks up the matched member and builds the resolved expression from member.Name, preserving the canonical member casing in output.

Comment on lines +551 to +575
PSPropertyExpression literalExpression = GetLiteralPropertyExpression(expression, inputObject);
return literalExpression is null
? expression.ResolveNames(inputObject)
: new List<PSPropertyExpression> { literalExpression };
}

private static List<PSPropertyExpressionResult> GetPropertyValues(PSPropertyExpression expression, PSObject inputObject)
{
PSPropertyExpression literalExpression = GetLiteralPropertyExpression(expression, inputObject);
return literalExpression is null
? expression.GetValues(inputObject)
: literalExpression.GetValues(inputObject);
}

private static PSPropertyExpression GetLiteralPropertyExpression(PSPropertyExpression expression, PSObject inputObject)
{
if (expression.Script is not null)
{
return null;
}

string propertyName = WildcardPattern.Unescape(expression.ToString());
return inputObject.Properties[propertyName] is null
? null
: new PSPropertyExpression(propertyName, isResolved: true);
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 2ce27ae3d: GetPropertyValues now reuses ResolvePropertyNames, so the literal-then-fallback flow is centralized instead of duplicated between the two call sites.

Comment on lines +549 to +555
private static List<PSPropertyExpression> ResolvePropertyNames(PSPropertyExpression expression, PSObject inputObject)
{
PSPropertyExpression literalExpression = GetLiteralPropertyExpression(expression, inputObject);
return literalExpression is null
? expression.ResolveNames(inputObject)
: new List<PSPropertyExpression> { literalExpression };
}
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 2ce27ae3d: unescaped wildcard expressions now keep the existing wildcard expansion behavior. Literal resolution only applies when the caller used an escaped wildcard property name, so Select-Object -Property 'Foo*' still expands matching properties.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Select-Object cannot target properties that literally contain wildcard characters

2 participants