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

时间:2013-02-20 00:14:04

标签: powershell powercli

出于性能原因,我已开始重写我的VMware每日报告以使用Get-View,而不是尽可能使用相关的PowerCLI命令。对此的一个小麻烦是返回的视图对象通常具有许多属性,其中许多属于对象本身。有些属性嵌套了四层或更多层。

所以我试图创建一个函数,它将输出一个对象的所有属性,以及该属性的完整路径。然后可以将其传送到Where-Object,以便更轻松地查找特定属性。因此,要在$ v中存储的VMware.Vim.VirtualMachine对象上查找与Host相关的属性,我会输入类似的内容:

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

理想情况下,这将返回$ v的所有嵌套属性的列表,其中包含单词“Host”。

我该怎么做?

1 个答案:

答案 0 :(得分:11)

也许有一种更简单的方法可以做到这一点,但这就是我想出的:

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个嵌套属性,这是一种更容易找到所需内容的方法。希望这可以帮助别人。