How can you use an object's property in a double-quoted string?

I have the following code:

$DatabaseSettings = @();
$NewDatabaseSetting = "" | select DatabaseName, DataFile, LogFile, LiveBackupPath;
$NewDatabaseSetting.DatabaseName = "LiveEmployees_PD";
$NewDatabaseSetting.DataFile = "LiveEmployees_PD_Data";
$NewDatabaseSetting.LogFile = "LiveEmployees_PD_Log";
$NewDatabaseSetting.LiveBackupPath = '\\LiveServer\LiveEmployeesBackups';
$DatabaseSettings += $NewDatabaseSetting;

When I try to use one of the properties in a string execute command:

& "$SQlBackupExePath\SQLBackupC.exe" -I $InstanceName -SQL `
  "RESTORE DATABASE $DatabaseSettings[0].DatabaseName FROM DISK = '$tempPath\$LatestFullBackupFile' WITH NORECOVERY, REPLACE, MOVE '$DataFileName' TO '$DataFilegroupFolder\$DataFileName.mdf', MOVE '$LogFileName' TO '$LogFilegroupFolder\$LogFileName.ldf'"

It tries to just use the value of $DatabaseSettings rather than the value of $DatabaseSettings[0].DatabaseName, which is not valid.
My workaround is to have it copied into a new variable.

How can I access the object's property directly in a double-quoted string?


Solution 1:

When you enclose a variable name in a double-quoted string it will be replaced by that variable's value:

$foo = 2
"$foo"

becomes

"2"

If you don't want that you have to use single quotes:

$foo = 2
'$foo'

However, if you want to access properties, or use indexes on variables in a double-quoted string, you have to enclose that subexpression in $():

$foo = 1,2,3
"$foo[1]"     # yields "1 2 3[1]"
"$($foo[1])"  # yields "2"

$bar = "abc"
"$bar.Length"    # yields "abc.Length"
"$($bar.Length)" # yields "3"

PowerShell only expands variables in those cases, nothing more. To force evaluation of more complex expressions, including indexes, properties or even complete calculations, you have to enclose those in the subexpression operator $( ) which causes the expression inside to be evaluated and embedded in the string.

Solution 2:

@Joey has the correct answer, but just to add a bit more as to why you need to force the evaluation with $():

Your example code contains an ambiguity that points to why the makers of PowerShell may have chosen to limit expansion to mere variable references and not support access to properties as well (as an aside: string expansion is done by calling the ToString() method on the object, which can explain some "odd" results).

Your example contained at the very end of the command line:

...\$LogFileName.ldf

If properties of objects were expanded by default, the above would resolve to

...\

since the object referenced by $LogFileName would not have a property called ldf, $null (or an empty string) would be substituted for the variable.