RJ Cantrell
RJ Cantrell

Reputation: 161

Why is my PowerShell function's parameter showing up as empty/blank?

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

Answers (2)

Aaron Jensen
Aaron Jensen

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

latkin
latkin

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

Related Questions