I'm trying to call vswhere.exe to find various Visual Studio executables for CI purposes. In order to simplify this, I've created a wrapper function:
function Run-VsWhere { &("${env:ProgramFiles(x86)}/Microsoft Visual Studio/Installer/vswhere.exe") $args }
function Find-VSWherePath([string[]] $workloads, [string] $pathGlob) {
Run-VsWhere -products * -prerelease -latest -requires $workloads -requiresAny -find $pathGlob
}
This works perfectly for single workloads, e.g. for MSBuild:
Find-VSWherePath "Microsoft.Component.MSBuild" "MSBuild/**/Bin/MSBuild.exe"
> C:\Program Files (x86)\Microsoft Visual Studio\2019\Preview\MSBuild\Current\Bin\MSBuild.exe
... but falls apart for multiple ones like VSTest:
Find-VSWherePath "Microsoft.VisualStudio.Workload.ManagedDesktop","Microsoft.VisualStudio.Workload.Web" "**/TestPlatform/vstest.console.exe"
> (nothing)
If I replace the call to vswhere with a call to echoargs, it demonstrates exactly what's going wrong. MSBuild:
> Arg 0 is <-products>
> Arg 1 is <*>
> Arg 2 is <-prerelease>
> Arg 3 is <-latest>
> Arg 4 is <-requires>
> Arg 5 is <Microsoft.Component.MSBuild>
> Arg 6 is <-requiresAny>
> Arg 7 is <-find>
> Arg 8 is <MSBuild/**/Bin/MSBuild.exe>
vs VSTest:
> Arg 0 is <-products>
> Arg 1 is <*>
> Arg 2 is <-prerelease>
> Arg 3 is <-latest>
> Arg 4 is <-requires>
> Arg 5 is <Microsoft.VisualStudio.Workload.ManagedDesktop Microsoft.VisualStudio.Workload.Web>
> Arg 6 is <-requiresAny>
> Arg 7 is <-find>
> Arg 8 is <**/TestPlatform/vstest.console.exe>
The issue is that the $workloads parameter is being passed to Run-VsWhere as a single parameter joined by a space, instead of one parameter per element in the array - how can I force it to pass as I need? I've tried every combination of splatting, splitting, joining, single-quoting, double-quoting... but nothing seems to work.
function Run-VsWhere { "..." $args }should throw an error when trying to define the function. Did you omit the call operator?"${env:ProgramFiles(x86)}/..." $argsinstead of invoking the program. Does it show the commandline you expect? Do you get a result when running that commandine manually?@argsinstead of$args. That should unroll the array.