在 PowerShell 中将成员 AliasProperty 添加到子 属性
Add-Member AliasProperty to sub property in PowerShell
我有一个包含对象数组的对象 属性。
PS C:\> $Object
GroupType : Object
StateRevCounter : 3846
SchemaTag : Computer
PropGroupList : {DSM.MdsPropGroup, DSM.MdsPropGroup, DSM.MdsPropGroup, DSM.MdsPropGroup...}
PS C:\> $Object.PropGroupList
Tag PropertyList
--- ------------
BasicInventory {DSM.MdsTypedPropertyOfString, DSM.MdsTypedPropertyOfString, DSM.MdsTypedPr...
ClientInfo {DSM.MdsTypedPropertyOfNullableOfDateTime, DSM.MdsTypedPropertyOfNullableOf...
Computer {DSM.MdsTypedPropertyOfString, DSM.MdsTypedPropertyOfNullableOfDateTime, DS...
CustomPatchManagement {DSM.MdsTypedPropertyOfNullableOfBoolean, DSM.MdsTypedPropertyOfString}
HardwareBasedRemoteMgmt {DSM.MdsTypedPropertyOfString, DSM.MdsTypedPropertyOfNullableOfBoolean, DSM...
PS C:\> $Object.PropGroupList.PropertyList
TypedValue Tag Type
---------- --- ----
7.4.1.4461 ClientVersion String
Client ComputerRole Option
169 CPUArchitecture CatalogLink
2262 CPUType CatalogLink
DSMCLIENT00.Computers.ideri.dev DirectoryContext String
DSMClient00.ideri.dev FullQualifiedName String
InfrastructureRole Option
000C29E1B2FD InitialMACAddress String
227 InstalledOS CatalogLink
315 InstalledOSCulture CatalogLink
1458 InstalledOSFlavor CatalogLink
Windows 10 Enterprise 1511 InstalledOSFriendlyName String
DSM.MdsVersion InstalledOSVersion Version
4193 InstalledRAM Int32
66057 LastBootServer Int32
.....
现在我想为 $Object 创建 AliasProperties,以直接在 $Object 的输出中显示 $Object.PropGroupList.PropertyList
的值,并在更改 AliasProperty 时更新正确位置的值。
期望的输出:
PS C:\> $Object
BasicInventory_ClientVersion : 7.4.1.4461
BasicInventory_ComputerRole : Client
BasicInventory_CPUArchitecture : 169
...
GroupType : Object
StateRevCounter : 3846
SchemaTag : Computer
PropGroupList : {DSM.MdsPropGroup, DSM.MdsPropGroup, DSM.MdsPropGroup, DSM.MdsPropGroup...}
因此,如果我随后将 BasicInventory_ClientVersion 更新为 10.4.2.3333,子 属性(数组)中的相应值也会更新,反之亦然。
Add-Member -MemberType AliasProperty
甚至可以做到这一点吗?或者我可以只为对象根中的属性添加 AliasProperties 吗?
问候
塞博
您可以使用 Add-Member
添加成员类型 ScriptProperty
。但是,构建对象是一个相当手动的过程。这是一个使用两个属性 ClientVersion
和 ComputerRole
.
的示例
$object | Add-Member -MemberType ScriptProperty -Name "BasicInventory_ClientVersion" -Value {
(($this.propgrouplist | Where Tag -eq 'BasicInventory').propertylist | where Tag -eq 'ClientVersion').TypedValue
}
$object | Add-Member -MemberType ScriptProperty -Name "BasicInventory_ComputerRole" -Value {
(($this.propgrouplist | Where Tag -eq 'BasicInventory').propertylist | where Tag -eq 'ComputerRole').TypedValue
}
现在您可以更新源 属性 并将其反映在脚本中属性。
# Properties Before Change
$object | fl
GroupType : Object
PropGroupList : @{Tag=BasicInventory; PropertyList=System.Object[]}
BasicInventory_ClientVersion : 7.4.1.4461
BasicInventory_ComputerRole : Client
# Properties After Change
($Object.PropGroupList.PropertyList | Where Tag -eq 'ClientVersion').TypedValue = '20.3.4'
$object | fl
GroupType : Object
PropGroupList : @{Tag=BasicInventory; PropertyList=System.Object[]}
BasicInventory_ClientVersion : 20.3.4
BasicInventory_ComputerRole : Client
尝试使用变量使其动态化时要小心。脚本属性 值中使用的任何变量都将在根据调用范围中定义的变量调用对象时进行计算。例如,如果您将值指定为 {$tag}
,则需要在检索 $object
之前在某处定义 $tag
。
正如@AdminOfThings 所建议的,我最终使用了 ScriptProperty。谢谢。
我最终构建了一个函数来添加具有正确链接的属性到数组。
如您所见,我必须先将脚本块组成一个字符串,以便首先解析我的变量值。如果我直接将它写在脚本块中,变量 $prop.Tag
就不会被解析,因为它没有在脚本块中设置。
function ExpandObjectMdsPropGroupList ($ObjectList)
{
foreach($obj in $ObjectList)
{
$PropGroupList = $obj.Propgrouplist
foreach($propGrp in $PropGroupList)
{
foreach($prop in $propGrp.PropertyList)
{
# compose the getter
$GetterScriptBlockAsString = "(`$this.propGroupList.PropertyList | Where-Object{`$_.Tag -eq `"$($prop.Tag)`"}).TypedValue"
$GetterScriptBlock = [scriptblock]::Create($GetterScriptBlockAsString)
# compose the setter
[string]$typeOfPropTypedValue = $null
try{
# get the type of TypedValue
$typeOfPropTypedValue = $prop.TypedValue.GetType()
}catch{
# If TypedValue is null we have to get the type from get-member
$memberType = ($prop | Get-Member -Name TypedValue).Definition
$typeOfPropTypedValue = ($memberType.Remove($memberType.IndexOf(' ')))
}
if($typeOfPropTypedValue){
$typeOfPropTypedValue = "[$typeOfPropTypedValue]"
}
$SetterScriptBlockAsString = "param($typeOfPropTypedValue`$val);(`$this.propGroupList.PropertyList | Where-Object{`$_.Tag -eq `"$($prop.Tag)`"}).TypedValue = `$val"
$SetterScriptBlock = [scriptblock]::Create($SetterScriptBlockAsString)
# Add the member to the object
$obj | Add-Member -MemberType ScriptProperty -Name "$($propGrp.Tag)_$($prop.Tag)" -Value $GetterScriptBlock -SecondValue $SetterScriptBlock
}
}
}
$ObjectList
}
现在我可以在任何带有 PropGroupList 的对象上使用该函数作为 属性 并且它添加 ScriptProperties 而不管列表中的 PropGroups 是什么。
多亏了 getter 和 setter,我可以更新任一侧的值。
问候
塞博
我有一个包含对象数组的对象 属性。
PS C:\> $Object
GroupType : Object
StateRevCounter : 3846
SchemaTag : Computer
PropGroupList : {DSM.MdsPropGroup, DSM.MdsPropGroup, DSM.MdsPropGroup, DSM.MdsPropGroup...}
PS C:\> $Object.PropGroupList
Tag PropertyList
--- ------------
BasicInventory {DSM.MdsTypedPropertyOfString, DSM.MdsTypedPropertyOfString, DSM.MdsTypedPr...
ClientInfo {DSM.MdsTypedPropertyOfNullableOfDateTime, DSM.MdsTypedPropertyOfNullableOf...
Computer {DSM.MdsTypedPropertyOfString, DSM.MdsTypedPropertyOfNullableOfDateTime, DS...
CustomPatchManagement {DSM.MdsTypedPropertyOfNullableOfBoolean, DSM.MdsTypedPropertyOfString}
HardwareBasedRemoteMgmt {DSM.MdsTypedPropertyOfString, DSM.MdsTypedPropertyOfNullableOfBoolean, DSM...
PS C:\> $Object.PropGroupList.PropertyList
TypedValue Tag Type
---------- --- ----
7.4.1.4461 ClientVersion String
Client ComputerRole Option
169 CPUArchitecture CatalogLink
2262 CPUType CatalogLink
DSMCLIENT00.Computers.ideri.dev DirectoryContext String
DSMClient00.ideri.dev FullQualifiedName String
InfrastructureRole Option
000C29E1B2FD InitialMACAddress String
227 InstalledOS CatalogLink
315 InstalledOSCulture CatalogLink
1458 InstalledOSFlavor CatalogLink
Windows 10 Enterprise 1511 InstalledOSFriendlyName String
DSM.MdsVersion InstalledOSVersion Version
4193 InstalledRAM Int32
66057 LastBootServer Int32
.....
现在我想为 $Object 创建 AliasProperties,以直接在 $Object 的输出中显示 $Object.PropGroupList.PropertyList
的值,并在更改 AliasProperty 时更新正确位置的值。
期望的输出:
PS C:\> $Object
BasicInventory_ClientVersion : 7.4.1.4461
BasicInventory_ComputerRole : Client
BasicInventory_CPUArchitecture : 169
...
GroupType : Object
StateRevCounter : 3846
SchemaTag : Computer
PropGroupList : {DSM.MdsPropGroup, DSM.MdsPropGroup, DSM.MdsPropGroup, DSM.MdsPropGroup...}
因此,如果我随后将 BasicInventory_ClientVersion 更新为 10.4.2.3333,子 属性(数组)中的相应值也会更新,反之亦然。
Add-Member -MemberType AliasProperty
甚至可以做到这一点吗?或者我可以只为对象根中的属性添加 AliasProperties 吗?
问候 塞博
您可以使用 Add-Member
添加成员类型 ScriptProperty
。但是,构建对象是一个相当手动的过程。这是一个使用两个属性 ClientVersion
和 ComputerRole
.
$object | Add-Member -MemberType ScriptProperty -Name "BasicInventory_ClientVersion" -Value {
(($this.propgrouplist | Where Tag -eq 'BasicInventory').propertylist | where Tag -eq 'ClientVersion').TypedValue
}
$object | Add-Member -MemberType ScriptProperty -Name "BasicInventory_ComputerRole" -Value {
(($this.propgrouplist | Where Tag -eq 'BasicInventory').propertylist | where Tag -eq 'ComputerRole').TypedValue
}
现在您可以更新源 属性 并将其反映在脚本中属性。
# Properties Before Change
$object | fl
GroupType : Object
PropGroupList : @{Tag=BasicInventory; PropertyList=System.Object[]}
BasicInventory_ClientVersion : 7.4.1.4461
BasicInventory_ComputerRole : Client
# Properties After Change
($Object.PropGroupList.PropertyList | Where Tag -eq 'ClientVersion').TypedValue = '20.3.4'
$object | fl
GroupType : Object
PropGroupList : @{Tag=BasicInventory; PropertyList=System.Object[]}
BasicInventory_ClientVersion : 20.3.4
BasicInventory_ComputerRole : Client
尝试使用变量使其动态化时要小心。脚本属性 值中使用的任何变量都将在根据调用范围中定义的变量调用对象时进行计算。例如,如果您将值指定为 {$tag}
,则需要在检索 $object
之前在某处定义 $tag
。
正如@AdminOfThings 所建议的,我最终使用了 ScriptProperty。谢谢。 我最终构建了一个函数来添加具有正确链接的属性到数组。
如您所见,我必须先将脚本块组成一个字符串,以便首先解析我的变量值。如果我直接将它写在脚本块中,变量 $prop.Tag
就不会被解析,因为它没有在脚本块中设置。
function ExpandObjectMdsPropGroupList ($ObjectList)
{
foreach($obj in $ObjectList)
{
$PropGroupList = $obj.Propgrouplist
foreach($propGrp in $PropGroupList)
{
foreach($prop in $propGrp.PropertyList)
{
# compose the getter
$GetterScriptBlockAsString = "(`$this.propGroupList.PropertyList | Where-Object{`$_.Tag -eq `"$($prop.Tag)`"}).TypedValue"
$GetterScriptBlock = [scriptblock]::Create($GetterScriptBlockAsString)
# compose the setter
[string]$typeOfPropTypedValue = $null
try{
# get the type of TypedValue
$typeOfPropTypedValue = $prop.TypedValue.GetType()
}catch{
# If TypedValue is null we have to get the type from get-member
$memberType = ($prop | Get-Member -Name TypedValue).Definition
$typeOfPropTypedValue = ($memberType.Remove($memberType.IndexOf(' ')))
}
if($typeOfPropTypedValue){
$typeOfPropTypedValue = "[$typeOfPropTypedValue]"
}
$SetterScriptBlockAsString = "param($typeOfPropTypedValue`$val);(`$this.propGroupList.PropertyList | Where-Object{`$_.Tag -eq `"$($prop.Tag)`"}).TypedValue = `$val"
$SetterScriptBlock = [scriptblock]::Create($SetterScriptBlockAsString)
# Add the member to the object
$obj | Add-Member -MemberType ScriptProperty -Name "$($propGrp.Tag)_$($prop.Tag)" -Value $GetterScriptBlock -SecondValue $SetterScriptBlock
}
}
}
$ObjectList
}
现在我可以在任何带有 PropGroupList 的对象上使用该函数作为 属性 并且它添加 ScriptProperties 而不管列表中的 PropGroups 是什么。
多亏了 getter 和 setter,我可以更新任一侧的值。
问候 塞博