views:

215

answers:

2

Basically 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;

However when I try to use one of the properites 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 doesn't work (it tries to just use the $DatabaseSettings which is not valid). ATM i have copied into a new var but this seems a bit silly!

Anyone know how to do it, or if it is even possible?

+5  A: 

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. You can 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.

Joey
+3  A: 

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

Your example code has a perfect example as to why in string expansion only the primary reference is expanded (in string expansion, the primary 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.

Steven Murawski
Nice find. I actually wasn't completely sure what his problem was but trying to access properties from within a string smelled bad :)
Joey
Thanks guys! Johannes why do you think accessing properties in a string smells bad? How would suggest it is done?
caveman_dick
caveman: It just was a thing that caught my eye as being a potential error cause. You can certainly do it and it's nothing weird, but when omitting the $() operator it screams "Fail" because it can't work. Thus my answer was just an educated guess about what your poblem could be, using the first possible failure cause I could see. Sorry if it looked like it, but that comment wasn't referring to any best practice or so.
Joey
Good you had me worried there! ;) When I first started using powershell I thought the variable in a string was a bit weird, but it is quite handy. I've just not managed to find a definitive place that I can look for syntax help.
caveman_dick