如何递归枚举对象的属性?

10

出于性能方面的考虑,我已开始重写我的VMware日常报告,尽可能使用Get-View而非相关的PowerCLI命令。但是这样做会产生一个小问题,即返回的视图对象通常有许多属性,并且其中许多属性本身也是对象。有些属性嵌套深度达到四层或更多。

因此,我正在尝试创建一个函数,它将输出对象的所有属性以及该属性的完整路径。然后可以将其管道传递给Where-Object,以使查找特定属性变得更加容易。因此,要在存储在$v中的VMware.Vim.VirtualMachine对象上查找与Host相关的属性,我需要输入类似于:

Get-Properties -Object $v | ? {$_ -match "Host"}
理想情况下,这将返回$v的所有嵌套属性列表,其中包含单词“Host”。
我该如何做到这一点?
1个回答

17
也许有更简单的方法,但这是我想到的办法:
function Get-Properties($Object, $MaxLevels="5", $PathName = "`$_", $Level=0)
{
    <#
        .SYNOPSIS
        Returns a list of all properties of the input object

        .DESCRIPTION
        Recursively 

        .PARAMETER Object
        Mandatory - The object to list properties of

        .PARAMETER MaxLevels
        Specifies how many levels deep to list

        .PARAMETER PathName
        Specifies the path name to use as the root. If not specified, all properties will start with "."

        .PARAMETER Level
        Specifies which level the function is currently processing. Should not be used manually.

        .EXAMPLE
        $v = Get-View -ViewType VirtualMachine -Filter @{"Name" = "MyVM"}
        Get-Properties $v | ? {$_ -match "Host"}

        .NOTES
            FunctionName : 
            Created by   : KevinD
            Date Coded   : 02/19/2013 12:54:52
        .LINK
            http://stackoverflow.com/users/1298933/kevind
     #>

    if ($Level -eq 0) 
    { 
        $oldErrorPreference = $ErrorActionPreference
        $ErrorActionPreference = "SilentlyContinue"
    }

    #Initialize an array to store properties
    $props = @()

    # Get all properties of this level
    $rootProps = $Object | Get-Member -ErrorAction SilentlyContinue | Where-Object { $_.MemberType -match "Property"} 

    # Add all properties from this level to the array.
    $rootProps | ForEach-Object { $props += "$PathName.$($_.Name)" }

    # Make sure we're not exceeding the MaxLevels
    if ($Level -lt $MaxLevels)
    {

        # We don't care about the sub-properties of the following types:
        $typesToExclude = "System.Boolean", "System.String", "System.Int32", "System.Char"

        #Loop through the root properties
        $props += $rootProps | ForEach-Object {

                    #Base name of property
                    $propName = $_.Name;

                    #Object to process
                    $obj = $($Object.$propName)

                    # Get the type, and only recurse into it if it is not one of our excluded types
                    $type = ($obj.GetType()).ToString()

                    # Only recurse if it's not of a type in our list
                    if (!($typesToExclude.Contains($type) ) )
                    {

                        #Path to property
                        $childPathName = "$PathName.$propName"

                        # Make sure it's not null, then recurse, incrementing $Level                        
                        if ($obj -ne $null) 
                        {
                            Get-Properties -Object $obj -PathName $childPathName -Level ($Level + 1) -MaxLevels $MaxLevels }
                        }
                    }
    }

    if ($Level -eq 0) {$ErrorActionPreference = $oldErrorPreference}
    $props
}

使用命令运行时

Get-Properties -Object $v | ? {$_ -match "Host" }

它返回

$_.Capability.HostBasedReplicationSupported
$_.Client.CertificateError.Method.DeclaringType.Assembly.HostContext
$_.Client.CertificateError.Method.Module.Assembly.HostContext
$_.Client.CertificateError.Method.ReflectedType.Assembly.HostContext
$_.Client.CertificateError.Method.ReturnType.Assembly.HostContext
$_.Client.ServiceContent.HostProfileManager
$_.Client.ServiceContent.HostProfileManager
$_.Client.ServiceContent.HostProfileManager.Type
$_.Client.ServiceContent.HostProfileManager.Value
$_.Config.Hardware.Device.Backing.HostPointingDevice
$_.Config.Hardware.Device.Backing.HostPointingDevice
$_.Config.Hardware.Device.Backing.HostPointingDevice
$_.Config.Hardware.Device.Backing.HostPointingDevice
$_.Config.Hardware.Device.Backing.HostPointingDevice
$_.Config.Hardware.Device.Backing.HostPointingDevice
$_.Config.Hardware.Device.Backing.HostPointingDevice
$_.Config.Hardware.Device.Backing.HostPointingDevice
$_.Config.Hardware.Device.Backing.HostPointingDevice
$_.Config.Hardware.Device.Backing.HostPointingDevice
$_.Config.Hardware.Device.Backing.HostPointingDevice
$_.Config.Hardware.Device.Backing.HostPointingDevice
$_.Config.Tools.SyncTimeWithHost
$_.Guest.HostName
$_.Guest.IpStack.DnsConfig.HostName
$_.Guest.Net.DnsConfig.HostName
$_.Runtime.Host
$_.Runtime.Host
$_.Runtime.Host.Type
$_.Runtime.Host.Value
$_.Summary.Guest.HostName
$_.Summary.QuickStats.HostMemoryUsage
$_.Summary.Runtime.Host
$_.Summary.Runtime.Host
$_.Summary.Runtime.Host.Type
$_.Summary.Runtime.Host.Value

考虑到 VMware.Vim.VirtualMachine 对象有5087个嵌套属性,这是更容易找到你要查找的内容的方法。希望这能帮助其他人。


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