Reputation: 161
On a whim, in order to learn PowerShell, which I know I'm woefully behind on, I decided to write a super simple script to use MSBuild to clean a bunch of solutions in code, then build them with a certain set of arguments. Here's the script:
$sourceDir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
$cleanArgs = '/t:clean /verbosity:q /nologo /P:Configuration=Debug'
$buildArgs = '/verbosity:q /nologo /P:Platform="Any CPU";Configuration=Debug'
$solutions = @("asdf.sln","qwer.sln","zxcv.sln","yuio.sln","hjkl.sln","nm.sln")
function buildWithArgs([string[]]$solutionsToBuild = @(), [string]$args = 'default')
{
Write-Host args: $args
foreach($sln in $solutionsToBuild)
{
& $env:WINDIR\Microsoft.NET\Framework64\v4.0.30319\msbuild.exe "$sourceDir\$sln $args" | Out-Default
}
}
buildWithArgs $solutions $buildArgs
buildWithArgs $solutions $cleanArgs
Now, my problem is that the function "buildWithArgs" doesn't respect the $args parameter, which is always empty when I run or debug the script, no matter what I pass in. The $solutionsToBuild parameter works flawlessly, however. Do I have improper syntax? Even if it were the case that my $cleanArgs string was somehow improperly formatted or not escaped, I can't even make the function work with simple strings like "asdf", as $args is always empty when I run it. Thanks for any help you can provide to what is assuredly some small, silly error!
Upvotes: 4
Views: 4454
Reputation: 26749
First, $args
is a special, built-in parameter in PowerShell, which represents all the arguments to a function. One of the side-effects to this is you can't see its value in the ISE debugger. Try changing its name to MSBuildArgs
.
Make sure you define, buildArgs
and cleanArgs
as arrays. You're defining them as one single string. You do this so you can use PowerShell's splat operator (@
instead of $
when referencing a variable), which sends each argument in an array as a parameter to a command.
Lastly, you don't need to quote parameters that are stored in variables. PowerShell will do any quoting for you.
After making these changes, you'll have something like this:
$sourceDir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
$cleanArgs = @('/t:clean','/verbosity:q','/nologo','/P:Configuration=Debug')
$buildArgs = @('/verbosity:q','/nologo','/P:Platform="Any CPU";Configuration=Debug')
$solutions = @("asdf.sln","qwer.sln","zxcv.sln","yuio.sln","hjkl.sln","nm.sln")
function buildWithArgs([string[]]$solutionsToBuild = @(), [string[]]$MSBuildArgs= 'default')
{
Write-Host args: $args
foreach($sln in $solutionsToBuild)
{
$msbuildPath = Join-Path $env:WINDIR Microsoft.NET\Framework64\v4.0.30319\msbuild.exe -Resolve
& $msbuildPath (Join-Path $sourceDir $sln -Resolve) @MSBuildArgs | `
Out-Default
}
}
buildWithArgs $solutions $buildArgs
buildWithArgs $solutions $cleanArgs
Upvotes: 3
Reputation: 16792
$args
is a special automatic variable in powershell functions. It contains an array of parameters which are not otherwise bound to the declared parameters of the function. By plain bad luck/inexperience, you happened to name one of your declared parameters the same, which will cause issues.
If you rename your parameter to something else, say $BuildArgs
, it should be properly bound.
Note, however, that your current code will execute msbuild with a single parameter consisting of the solution path and args together. It is not the syntax to invoke msbuild with multiple arguments. If this causes issues for you I would suggest opening another question or searching online for that particular issue, just so this question does not get too big.
Upvotes: 2