Determine filterable attributes of returned Powershell object

Often when I'm scripting, I will be trying out a command but will want to filter the results. In order to find out what I'm able to filter on I need to know what filterable attributes are going to be available.

For example, I want to get a list of installed features but need to filter by installed only. The Get-InstalledFeature CMDlet doesn't have an -InstalledOnly type flag, so i need to filter the results. To find out what I can filter on i'll do something like

(Get-InstalledFeature)[0] | fl


Get-InstalledFeature | Select -First 1 | fl

and will find that I can (intuitively, I should say) filter on Installed. The resulting command is

Get-InstalledFeature | ?  { $_.Installed }

Is there an easier way to find out the filterable properties? Or perhaps I could be working differently? Or maybe I should just shut up and be happy that it's already so easy!

Get-Help doesn't really help in this case as it doesn't tell me what I'm going to get back.

Surely, this is what Get-Member is for???

<object> | Get-Member -MemberType Property

...or am I missing the point?

Some-CmdLet | Select * | Select -First 1

Will give you all the properties of the first object that is returned by the Cmdlet, but not necessarily all the properties that the objects returned by the Cmdlet are capable of containing.

Many if not most Cmdlets return dynamic objects, where a property simply will not exist (as opposed to the property existing but with a null or blank value) if that property is not populated in whatever provider from which the data is retrieved.

Edit2: Also, you can try something like this:

PS C:\> ForEach($P In $(Get-ADUser ryan -Properties *).PSObject.Properties) { $P.Name }

You can't really see what the Cmdlet could possibly return before you even run it, because of dynamic return objects... there is no knowing exactly what it will return before it's run. For instance, an object returned by Get-ADUser may or may not have the property 'EmployeeID' based on whether it is populated in AD or not. I don't mean that the property will have a value of $Null or [String]::Empty, I mean that property will literally not exist on that object.

If you use Set-StrictMode, this is especially apparent, as it will bark at you for trying to filter on a non-existent property of an object, even if the property exists on some but not other of the objects in the total returned set.

To elaborate on my point... when I'm authoring a Cmdlet, I can have logic in my Cmdlet, where if a certain condition is true, I can add a certain new property to the object to be returned, or otherwise the property is not returned...

if($x = $true) 
    $object | Add-Member -Type NoteProperty -Name $name -Value $y 
    # In this case, $object will NOT have the above property!