Proper use of Invoke-Expression?

powershell, scripting

Solution

Looks fine to me. Only thing I'd change is to use more Powershell features in place of fragile assumptions. E.g.:

use Join-Path instead of string concatenation

use the `Env:\` provider to look up the `%programfiles(x86)%` dir (or better yet, use the `HKML:\` provider to find the path - it's in SOFTWARE\Microsoft\VisualStudio\\InstallDir)

when I have to write a string that contains literal doublequotes and variable expansion, I usually fall back to the syntax below. Personal preference, obviously.

'"{0}" "{1}" /build "{2}"' -f $devenv, $solutionPath, $releaseProfile

In some cases I'd be inclined to use Process.Start() so that I could capture the stdout & stderr streams independently (and maybe even control stdin interactively, depending on the application).

PS - the '&' is not strictly necessary.

Problem

I've just recently completed my first nightly build script (first significant anything script, really) in powershell. I seem to have things working well, if not yet robustly (I haven't handled significant error-checking yet), but I found myself falling into an idiom around the `Invoke-Expression` cmdlet, and I'm wondering if I'm using it properly. Specifically, I use a series of variables to build up command-lines that I will use to build the solution, then run the solution's unit tests. e.g., something like: ``` $tmpDir = "C:\Users\<myuser>\Development\Autobuild" $solutionPath=$tmpDir+"\MyProj\MyProj.sln" $devenv="C:\Program Files (x86)\Microsoft Visual Studio 10.0\common7\ide\devenv" $releaseProfile="Release" $releaseCommandLine="`"$devenv`" `"$solutionPath`" /build `"$releaseProfile`"" ``` This works well enough, `$releaseCommandLine` contains the command line that I want to execute when I'm done. I then execute it via this line: ``` $output = Invoke-Expression "& $releaseCommandLine" ``` Is this the proper way to execute a manually-built command line from a powershell script? I thought initially that `Invoke-Command` would do it, but I must have been doing something wrong because I couldn't get that working at all for half an hour, and I got this working almost immediately. I've followed this same pattern a few other times in this same script. Is this a best-practice?

Original source