问题
I've started rewriting my VMware daily report to use Get-View, rather than the related PowerCLI commands wherever possible, for performance reasons. One minor inconvenience with this is that the view objects returned often have many properties, many of which are objects themselves. Some properties are nested four or more levels deep.
So I'm trying to create a function which will output all properties of an object, along with the full path to that property. This could then be piped to Where-Object, to make finding specific properties easier. So to find a property relating to Host on a VMware.Vim.VirtualMachine object stored in $v, I would type something like:
Get-Properties -Object $v | ? {$_ -match "Host"}
And ideally, this would return a list of all nested properties of $v which contain the word "Host".
How can I do this?
回答1:
Perhaps there is an easier way to do this, but here's what I came up with:
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
}
When running it using the command
Get-Properties -Object $v | ? {$_ -match "Host" }
it returns
$_.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
Considering that the VMware.Vim.VirtualMachine object has 5087 nested properties, this is a much easier way to find what you're looking for. Hopefully this can help someone else.
来源:https://stackoverflow.com/questions/14970079/how-to-recursively-enumerate-through-properties-of-object