为PSCustomObject添加多个ScriptMethods导致方法调用重复执行
问题根源与解决办法
你的代码中每个ScriptMethod调用都会执行多次,核心原因是**Add-Member的-PassThru参数使用不当,导致函数返回了多个对象**:
Add-Member默认会直接修改输入的对象,不需要返回结果;加上-PassThru参数后,它会把修改后的对象输出到管道中。- 你的函数没有明确的
return语句,PowerShell会自动将所有管道输出的内容作为函数返回值。三次Add-Member调用就输出了三个修改后的对象,因此$LocalCustomObject实际是一个包含3个对象的数组。 - 当你对数组调用方法时,PowerShell会自动遍历数组中的每个对象执行该方法,这就是为什么每个方法的执行次数等于ScriptMethod的添加数量。
解决方法1:移除-PassThru参数(推荐)
既然Add-Member会直接修改原对象,完全不需要-PassThru参数,直接删除即可:
function GetCustomObject { param( [Parameter(Mandatory=$true)] [String]$data ) $CustomObject = [PSCustomObject]@{ member = $data } $CustomObject | Add-Member -MemberType ScriptMethod -Name PrintMember -Value { Write-Host "Data is:" $this.member $this.member += ", again?" } $CustomObject | Add-Member -MemberType ScriptMethod -Name SomeOtherFunction -Value { Write-Host "SomeOtherFunction" } $CustomObject | Add-Member -MemberType ScriptMethod -Name YetAnotherFunction -Value { Write-Host "YetAnotherFunction" } # 明确返回单个自定义对象 return $CustomObject } $LocalCustomObject = GetCustomObject "Hello World" $LocalCustomObject.PrintMember() # 输出:Data is: Hello World $LocalCustomObject.SomeOtherFunction() # 输出:SomeOtherFunction $LocalCustomObject.YetAnotherFunction() # 输出:YetAnotherFunction
解决方法2:捕获-PassThru的输出(仅适合特殊场景)
如果必须使用-PassThru,需要将每次的输出赋值回$CustomObject,避免多余的管道输出:
function GetCustomObject { param( [Parameter(Mandatory=$true)] [String]$data ) $CustomObject = [PSCustomObject]@{ member = $data } # 将返回的对象赋值回变量,防止输出到管道 $CustomObject = $CustomObject | Add-Member -MemberType ScriptMethod -PassThru -Name PrintMember -Value { Write-Host "Data is:" $this.member $this.member += ", again?" } $CustomObject = $CustomObject | Add-Member -MemberType ScriptMethod -PassThru -Name SomeOtherFunction -Value { Write-Host "SomeOtherFunction" } $CustomObject = $CustomObject | Add-Member -MemberType ScriptMethod -PassThru -Name YetAnotherFunction -Value { Write-Host "YetAnotherFunction" } return $CustomObject }
更优雅的写法:使用PowerShell类(PS5.0+)
如果你的PowerShell版本支持5.0及以上,直接定义类会更清晰,避免手动添加成员的繁琐操作:
class CustomObject { [string]$member # 构造函数 CustomObject([string]$data) { $this.member = $data } [void] PrintMember() { Write-Host "Data is:" $this.member $this.member += ", again?" } [void] SomeOtherFunction() { Write-Host "SomeOtherFunction" } [void] YetAnotherFunction() { Write-Host "YetAnotherFunction" } } # 创建对象实例 $LocalCustomObject = [CustomObject]::new("Hello World") $LocalCustomObject.PrintMember() $LocalCustomObject.SomeOtherFunction() $LocalCustomObject.YetAnotherFunction()
内容的提问来源于stack exchange,提问作者Alex Apel
相关产品推荐
相关产品推荐

