Peter Seale Peter Seale - 4 months ago 24
PowerShell Question

How to invoke MSBuild from PowerShell using & operator?

I've just tested this on PowerShell v1.0. Setup is as follows:

Id CommandLine
-- -----------
1 $msbuild = "C:\Windows\Microsoft.NET\Framework\v3.5\msbuild.exe"
4 $a = "C:\some\project\or\other\src\Solution.sln /target:Clean /target:Build"


.

This line fails with an unintuitive error message:

Id CommandLine
-- -----------
5 & $msbuild $a


.

This line fails because & expects the first argument to be the command itself.

Id CommandLine
-- -----------
10 & "$msbuild $a"


.

This line works:

Id CommandLine
-- -----------
16 cmd /c "$msbuild $a"


.

Please explain. I'm more interested in why the & syntax isn't working, than an MSBuild-specific workaround.

Answer

The issues you are seeing results from PowerShell parsing arguments. In the first example, when PowerShell sees $a it passes it as a single parameter msbuild. We can see this using the echoargs utility from PSCX:.

PS> $a = "C:\some\project\or\other\src\Solution.sln /target:Clean /target:Build"
PS> & echoargs $a
Arg 0 is <C:\some\project\or\other\src\Solution.sln /target:Clean /target:Build>

The second example is even worse because you are telling powershell to invoke "$echoargs $a" as the command name and it isn't a valid command name.

The third line works because CMD.exe gets the expanded form of "$echoargs $a" as a single argument which is parses and executes:

You have a couple of options here. First I do it this way:

PS> & $msbuild C:\some\project\or\other\src\Solution.sln `
    /target:Clean /target:Build

The other option is to use Invoke-Expression like so:

PS> Invoke-Expression "$msbuild $a"

In general I try to be very careful with Invoke-Expression particularly if any part of the string that gets invoked is provided by the user.

Comments