如何向PowerShell数组添加自定义属性?

8

假设我有一个PowerShell数组$Sessions = @(),我要用PSCustomObjects填充它。如何向数组本身添加自定义属性?例如,我想要内建的$Sessions.Count$Sessions.Active,后者我想设置为活动会话计数。

我知道可以使用以下方式(有点不专业)向PSCustomObjects添加属性:

$MyCustomObject = "" | Select-Object Machine, UserName, SessionTime

不过,对数组进行此操作不会导致属性被添加。

那么我该如何实现我的目标?有没有办法创建自定义数组?


2
只需使用 Add-Member -InputObject $sessions ...?这就是它的作用。 - Matt
1
注意,向该数组附加 ($sessions += ...) 将替换该数组,因此删除了额外的属性。更安全的方法是使用具有不同属性的自定义对象来存储数组和状态。话虽如此,根据您想要使用此功能的情况,将添加到列表的属性更改为不同的列表变量 $activeSessions/$inactiveSessions 或将 Active 属性添加到单个会话对象可能更合适。 - Ansgar Wiechers
@Matt 如果你当初把它作为答案发布就好了...实际上我因为懒惰而滥用了Select-Object,这是阻止我找到解决方案的原因。谢谢。@AnsgarWiechers 感谢你提醒我使用+=,避免了我误放Add-Member调用。 - FatalMerlin
1
我忘了提到你所做的“选择”是创建空白对象的完全可接受的方法。在这方面,每个人都有自己的喜好。你的方法唯一的缺点在于对于类型和复杂属性等方面它可以过于基础。但仍然没有任何问题。 - Matt
2个回答

16

根据你提出的问题,答案就是在数组对象上使用 Add-Member 命令。

Add-Member -InputObject $sessions -MemberType NoteProperty -Name "State" -Value "Fabulous"

在创建对象之后给每个元素添加属性是类似的。

$sessions | ForEach-Object{
    $_ | Add-Member -MemberType NoteProperty -Name "State" -Value "Fabulous"
}

当然,这还有一个警告(我忘了)。来自评论:

不过要注意,将元素附加到该数组($sessions += ...)将替换数组,从而删除附加属性。

Ansgar Wiechers

根据您的用例,有其他选项可以满足您的需求。您可以将数组元素保存到单独的变量中:

# Check the current object state
$state = $object.Property .....

# Add to the appropriate array.
if($state -eq "Active"){
    $activeSessions += $object
} else {
    $inactiveSessions += $object
}

或者您仍然可以存储您的状态属性,并根据需要使用Where-Object进行后处理:

# Process each inactive session
$sessions | Where-Object{$_.State -eq "Active"} | ForEach-Object{}
为避免数组的破坏/重新创建问题,因为它可能会影响性能,您也可以使用一个ArrayList代替。

为避免破坏/重新创建数组的问题,这可能会导致性能降低,您还可以考虑使用ArrayList。

$myArray = New-Object System.Collections.ArrayList
Add-Member -InputObject $myArray -MemberType ScriptMethod -Name "NeverTellMeTheOdds" -Value {
    $this | Where-Object{$_ % 2 -ne 0}
}

$myArray.AddRange(1..10)
$myArray.NeverTellMeTheOdds()

请注意,该数组已经添加了其成员,然后我们添加了它的元素。


3

正如Matt所评论的那样,您可以通过将可枚举类型作为位置参数提供给 -InputObject 参数来使用 Add-Member

为了在添加新属性后允许调整大小,请使用通用的 List 而不是 @()

$list = [System.Collections.Generic.List[psobject]]::new()
$list.AddRange(@(
  [pscustomobject]@{SessionId = 1; Active = $true}
  [pscustomobject]@{SessionId = 2; Active = $false}
  [pscustomobject]@{SessionId = 3; Active = $true}
) -as [psobject[]])

Add-Member -InputObject $list -MemberType ScriptProperty -Name ActiveSessionCount -Value {
  return @($this |? Active -eq $true).Count
}

现在,您可以轻松地检索活动会话计数:
PS C:\> $list.ActiveSessionCount
2

1
我建议使用ArrayList。看来我们想法一致。 - Matt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接