如何从PowerShell向可执行文件传递字符串与数组混合参数?
解决PowerShell中传递数组参数给vswhere.exe的问题
我之前也碰到过一模一样的坑!问题根源在于PowerShell处理数组参数传递给外部命令的默认行为:当你直接把数组作为-requires的参数值时,PowerShell会把数组元素拼接成一个带引号的空格分隔字符串传递给vswhere,而不是把每个元素作为独立的命令行参数。如果你的工作负载ID包含空格(很多VS工作负载ID确实带点或空格),vswhere会把这个拼接后的字符串当成单个工作负载ID,自然找不到匹配的结果。
解决方案:用参数数组+Splatting传递参数
我们可以手动构建包含所有vswhere参数的数组,然后用PowerShell的splatting(@数组名语法)来展开数组,确保每个元素都被作为独立的命令行参数传递。下面是修改后的函数:
function Run-VsWhere { &("${env:ProgramFiles(x86)}/Microsoft Visual Studio/Installer/vswhere.exe") $args } function Find-VSWherePath([string[]] $workloads, [string] $pathGlob) { # 构建vswhere的参数数组 $vsWhereParams = @( '-products', '*', '-prerelease', '-latest', '-requiresAny' ) # 为每个工作负载添加独立的-requires参数 foreach ($workload in $workloads) { $vsWhereParams += '-requires', $workload } # 添加最后的-find参数 $vsWhereParams += '-find', $pathGlob # 使用splatting传递参数给vswhere Run-VsWhere @vsWhereParams }
为什么这样能行?
- 我们把每个工作负载ID都和
-requires配对添加到参数数组里,这样vswhere会收到多个-requires参数(每个对应一个工作负载),完全符合它的参数解析逻辑。 - Splatting语法
@vsWhereParams会告诉PowerShell把数组中的每个元素作为独立的命令行参数传递,不会把数组拼接成单个字符串,完美解决了空格和多参数的问题。
另一种简化写法(如果vswhere支持单个-requires后跟多个值)
如果你确认vswhere允许在单个-requires后面跟多个工作负载ID,也可以用更简洁的方式构建数组:
function Find-VSWherePath([string[]] $workloads, [string] $pathGlob) { $vsWhereParams = @( '-products', '*', '-prerelease', '-latest', '-requires' ) + $workloads + @( '-requiresAny', '-find', $pathGlob ) Run-VsWhere @vsWhereParams }
这种写法会生成-requires Workload1 Workload2的参数形式,和多个-requires的效果是一样的,具体看你个人习惯。
现在你再调用Find-VSWherePath传递多个工作负载数组,比如:
Find-VSWherePath -workloads @("Microsoft.VisualStudio.Workload.ManagedDesktop", "Microsoft.VisualStudio.Workload.NetWeb") -pathGlob "Common7\IDE\devenv.exe"
vswhere就能正确识别每个工作负载,返回你预期的结果了!
内容的提问来源于stack exchange,提问作者Ian Kemp - SO dead by AI greed
相关产品推荐
相关产品推荐

