Home > Software design >  Referencing an object's properties inside a string inside a foreach statement
Referencing an object's properties inside a string inside a foreach statement

Time:04-07

Apologies in advance! Self taught (read: just started with no coding experience), so I may have some incorrect terminology.

I have a function that loads registry user hives and produces a global variable $global:userprofiles with userprofile SIDs. This part works fine and looks like this:

SID                                          
---                                          
S-1-5-21-3411627100-1852253463-1168398051-500
S-1-5-21-3711182449-2936729792-314897268-1001
DEFAULTUSER

After that function I need to manipulate a registry key. If I do the following ....

$key = "Registry::HKEY_USERS\$($userprofile.SID)\Something\someone"
foreach($userprofile in $global:userprofiles)
{echo $key}

I get the following output:

Registry::HKEY_USERS\DEFAULTUSER\Something\someone
Registry::HKEY_USERS\DEFAULTUSER\Something\someone
Registry::HKEY_USERS\DEFAULTUSER\Something\someone

Not great.

If I put $key inside the foreach like this:

foreach($userprofile in $global:userprofiles)
{
  $key = "Registry::HKEY_USERS\$($userprofile.SID)\Something\someone"
  echo $key
}

It works:

Registry::HKEY_USERS\S-1-5-21-3411627100-1852253463-1168398051-500\Something\for\someone
Registry::HKEY_USERS\S-1-5-21-3711182449-2936729792-314897268-1001\Something\for\someone
Registry::HKEY_USERS\DEFAULTUSER\Something\for\someone

It took me entirely too long to figure that out and I can't seem to understand where I went wrong. Can someone provide an ELI5 so I don't goof something similar in the future?

CodePudding user response:

"Registry::HKEY_USERS\$($userprofile.SID)\Something\someone"

is an instance of an expandable (double-quoted) string ("..."), which means that expansion (interpolation) happens instantly.

That is, the value of $userprofile.SID at that time is substituted for the $($userprofile.SID) subexpression and a static string value is returned.

You mistakenly expected your string to act like a string template, to be (re-)interpolated every time it is accessed, based on then-current values.

  • This functionality requires a different approach: see this answer.

Placing your expandable string inside a foreach loop:

 foreach($userprofile in $global:userprofiles)  
  {
    $key = "Registry::HKEY_USERS\$($userprofile.SID)\Something\someone"  
    echo $key  
  }

solved your problem, because a new expandable string is then created in each iteration, where interpolation is based on the then-current values in each iteration.

  • Related