PowerShell函数中void作用及返回ArrayList的正确方式咨询
动态检测外接SSD盘符路径的PowerShell问题解析
需求背景
原本通过硬编码定义SSD盘符数组,为避免盘符变化导致失效,改为通过设备描述名动态检测已连接的外接SSD,收集其盘符路径到ArrayList中,未连接的则忽略。
原硬编码实现:
[System.Collections.ArrayList]$DestSSD = @( "X:\" #SSD-1 "T:\" #SSD-2 "A:\" #SSD-3 )
现有动态检测实现代码
function GetSSDsPath { [OutputType([System.Collections.ArrayList])] Param( [array]$SSDList, [System.Collections.ArrayList] $Target = @() ) foreach ($ssdName in $SSDList) { $SSD = Get-PSDrive | Where-Object {$_.Description -eq $ssdName} if($SSD){ [void]$Target.Add("$($SSD):\") #example "X:\" }else{ Write-Host "$($ssdName) not found" } } ,$Target } $ssdList = "SSD-1", "SSD-2", "SSD-3" [System.Collections.ArrayList]$DestSSD = GetSSDsPath $ssdList
疑问解答
1. [void]的作用
$Target.Add()方法执行后会返回元素在ArrayList中的索引值(比如第一个元素返回0,第二个返回1)。如果不用[void]包裹,这个索引值会被输出到PowerShell管道中,导致函数额外输出无关数字,污染最终返回的ArrayList内容。[void]的作用就是强制丢弃这个返回值,避免不必要的输出。
2. ,$Target的作用
PowerShell默认会展开集合返回:如果直接写return $Target,函数会把ArrayList中的每个盘符字符串单独输出,而非返回整个ArrayList对象。
,$Target是用逗号创建一个单元素数组,将ArrayList作为该数组的唯一元素。这样PowerShell会返回这个单元素数组,不会展开内部的ArrayList,调用方就能完整接收到预期的ArrayList对象。
如果替换成return $Target,函数实际返回的是多个独立字符串,接收时PowerShell会自动把这些字符串重新打包成新的ArrayList,但这会丢失原函数中对传入$Target的修改逻辑(比如提前传入已有元素的场景),导致结果不符合预期。
更优实现方法
可以简化逻辑,无需手动维护ArrayList,直接通过管道筛选生成结果,代码更简洁高效:
function Get-SSDsPath { [CmdletBinding()] param( [Parameter(Mandatory=$true)] [string[]]$SSDList ) # 一次性筛选所有匹配描述名的驱动器 $matchedDrives = Get-PSDrive | Where-Object { $SSDList -contains $_.Description } # 生成盘符路径集合 $paths = $matchedDrives.ForEach({ "$($_):\" }) # 输出未找到的SSD名称(需加-Verbose参数才显示) $notFound = $SSDList | Where-Object { $_ -notin $matchedDrives.Description } foreach ($name in $notFound) { Write-Verbose "$name not found" } # 若确实需要ArrayList则转换,否则直接返回普通数组即可 return [System.Collections.ArrayList]$paths } # 使用示例 $ssdList = "SSD-1", "SSD-2", "SSD-3" [System.Collections.ArrayList]$DestSSD = Get-SSDsPath -SSDList $ssdList -Verbose
优化点说明
- 用
[CmdletBinding()]支持Verbose等通用参数,将Write-Host替换为Write-Verbose,让日志输出更灵活(按需开启)。 - 一次性筛选所有匹配驱动器,减少循环次数,提升效率。
- 用
ForEach()方法批量生成路径,代码更简洁。 - 单独处理未找到的SSD名称,逻辑更清晰。
- 如果不需要
ArrayList的动态增删功能,直接返回普通数组(去掉[System.Collections.ArrayList]转换)即可,普通数组在PowerShell中性能更好,能满足大部分场景需求。
内容的提问来源于stack exchange,提问作者Filip
相关产品推荐
相关产品推荐

