在PSCustomObject中打印项目

时间:2017-05-15 18:49:35

标签: powershell

我想逐行打印自定义对象中的所有项目。我使用的陈述是:

TestObject ([PSCustomObject]@{item1=1 ;item2=2; item3=3},[PSCustomObject]@{item1=4;item2=5;item3=6}) -Verbose

我的功能定义如下:

function TestObject
{
  [CmdLetBinding()]
  Param(
  [parameter(Mandatory=$True]
  [object[]]$objectNames
  )
  Begin{}
  Process
  {
    foreach ($object in $objectNames)
    {
      $myItems =@()
      $myItems += $object
      foreach ($o in $myItems.GetEnumerator())
      {
         Write-Verbose "---------------$o--------------"
         foreach ($i in $o)
         {
           Write-Verbose "Name:$i.Key Value:$i.Value"
         }
      }
      Write-Verbose "$object"
    }
  }
  End{}
}

我预计输出如下:

VERBOSE: ---------------@{item1=1; item2=2; item3=3}--------------
VERBOSE: Name:item1 Value:1
VERBOSE: Name:item2 Value:2
VERBOSE: Name:item3 Value:3
VERBOSE: @{item1=1; item2=2; item3=3}
VERBOSE: ---------------@{item1=4; item2=5; item3=6}--------------
VERBOSE: Name:item1 Value:4
VERBOSE: Name:item2 Value:5
VERBOSE: Name:item3 Value:6
VERBOSE: @{item1=4; item2=5; item3=6}

相反,我得到了这个结果:

Enter image description here

如果我知道自定义对象的格式是由分号分隔的对(键,值)的集合,我该如何拆分自定义对象中的项?

1 个答案:

答案 0 :(得分:5)

你混淆了哈希表和自定义对象。仅仅因为你可以从另一个创建一个并不意味着它们的行为相同。 Hashtables可以通过GetEnumerator()进行枚举,生成DictionaryEntryKeyValue个属性的对象列表。

PS C:\> $ht = @{item1=1 ;item2=2; item3=3}
PS C:\> $ht

Name                           Value
----                           -----
item2                          2
item3                          3
item1                          1

PS C:\> "$ht"
System.Collections.Hashtable
PS C:\> $ht.GetType().FullName
System.Collections.Hashtable
PS C:\> $ht.GetEnumerator() | % { $_.GetType().FullName }
System.Collections.DictionaryEntry
System.Collections.DictionaryEntry
System.Collections.DictionaryEntry
PS C:\> $ht.GetEnumerator() | % { '{0} = {1}' -f $_.Key, $_.Value }
item2 = 2
item3 = 3
item1 = 1

当您将哈希表转换为自定义对象时,它将停止为哈希表(即使其字符串表示仍然看起来像哈希表),并且不再表现得像哈希表:

PS C:\> $o = [PSCustomObject]$ht
PS C:\> $o

     item2     item3     item1
     -----     -----     -----
         2         3         1

PS C:\> "$o"
@{item2=2; item3=3; item1=1}
PS C:\> $o.GetType().FullName
System.Management.Automation.PSCustomObject
PS C:\> $o.GetEnumerator()
Method invocation failed because [System.Management.Automation.PSCustomObject]
does not contain a method named 'GetEnumerator'.
At line:1 char:1
+ $o.GetEnumerator()
+ ~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (GetEnumerator:String) [],
                              RuntimeException
    + FullyQualifiedErrorId : MethodNotFound

要枚举对象的属性,请使用其内在属性:

PS C:\> $o.PSObject.Properties

MemberType      : NoteProperty
IsSettable      : True
IsGettable      : True
Value           : 2
TypeNameOfValue : System.Int32
Name            : item2
IsInstance      : True

MemberType      : NoteProperty
IsSettable      : True
IsGettable      : True
Value           : 3
TypeNameOfValue : System.Int32
Name            : item3
IsInstance      : True

MemberType      : NoteProperty
IsSettable      : True
IsGettable      : True
Value           : 1
TypeNameOfValue : System.Int32
Name            : item1
IsInstance      : True

PS C:\> $o.PSObject.Properties | % { '{0} = {1}' -f $_.Name, $_.Value }
item2 = 2
item3 = 3
item1 = 1

至于为什么输出字符串看起来不像你期望的那样:PowerShell不会在字符串中进行复杂的变量扩展。 "$i.Value"扩展为$i的字符串表示形式,后跟字符串".Value"。如果您想要字符串中对象的属性,则需要使用字符串连接:

"Name: " + $i.Name + ", Value: " + $i.Value

子表达式:

"Name: $($i.Name), Value: $($i.Value)"

或格式运算符:

"Name: {0}, Value: {1}" -f $i.Name, $i.Value

将您的功能简化为以下内容:

function Test-Object {
  [CmdletBinding()]
  Param(
    [Parameter(Mandatory=$true)]
    [array]$ObjectNames
  )

  foreach ($o in $ObjectNames) {
    foreach ($i in $o.PSObject.Properties) {
      Write-Verbose "Name: $($i.Name), Value: $($i.Value)"
    }
  }
}

它应该做你期望的。