2013-02-20 83 views
7

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

所以我试图创建一个函数,将输出一个对象的所有属性,以及该属性的完整路径。这可以通过管道连接到Where-Object,以便更轻松地查找特定属性。因此,要找到与主机存储在$ V A VMware.Vim.VirtualMachine对象上的属性,我会键入类似:

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

理想情况下,这将返回$ V所有嵌套属性的列表,其包含“主机”一词。

我该怎么做?

回答

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个嵌套属性,这是一种更简单的方式d你在找什么。希望这可以帮助别人。