4

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

or

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.

2
  • The question you asked is not what you wanted to know. You wanted to know how to get the filterable attributes of an object, which is returned after a Cmdlet is run, as evidenced by the answer you accepted. Mind if I edit your title to reflect what you were actually asking?
    – Ryan Ries
    Aug 6, 2013 at 12:14
  • Think that's already been done, but I have no problem as long as the title reflects the Q&A. It's not always easy to know 100% what you're asking for until the comments start to flow.
    – john
    Aug 6, 2013 at 16:53

2 Answers 2

3

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

<object> | Get-Member -MemberType Property

...or am I missing the point?

4
  • Yeah, but I think what he wanted was to get the properties that the object returned by a Cmdlet could possibly be, before actually having the object.
    – Ryan Ries
    Aug 5, 2013 at 20:43
  • It certainly works. Quite a simple one, because one would have thought you'd receive a list of properties of the collection not the obejcts it contains!
    – john
    Aug 5, 2013 at 20:47
  • Plus, to make it even easier, the Get-Member CMDlet has an alias of gm making it possible to just do <object> | gm. Getting only the properties might remove potential filtering data.
    – john
    Aug 5, 2013 at 20:52
  • Also be aware of the -Force and -View All parameters for Get-Member.
    – jscott
    Aug 6, 2013 at 12:25
3

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 }
AccountExpirationDate
accountExpires
AccountLockoutTime
AccountNotDelegated
AllowReversiblePasswordEncryption
BadLogonCount
badPwdCount
c
CannotChangePassword
CanonicalName
....
userAccountControl
userCertificate
UserPrincipalName
uSNChanged
uSNCreated
whenChanged
whenCreated
PropertyNames
PropertyCount

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 
}
Else
{
    # In this case, $object will NOT have the above property!
}
5
  • Lol, now what did I do with my sledgehammer?
    – john
    Aug 5, 2013 at 20:21
  • That command you gave me doesn't work for CMDlets that return collections of objects, it just spews them all out. I appreicate your comments regarding dynamic return, could you add them your answer?
    – john
    Aug 5, 2013 at 20:32
  • Yes I think 'before it is run' is perhaps asking a bit much. anything easier to type would suffice.
    – john
    Aug 5, 2013 at 20:54
  • Well then yes, $object | gm is obviously easier, but it does not satisfy your original question. You do not receive $object until after you run a Cmdlet.
    – Ryan Ries
    Aug 5, 2013 at 20:56
  • Not literally speaking. I was asking about simpler ways to get the list before I ran the command that actually applies the filter. I accept that it's not going to be possible to do it with every command, but for CMDlets that only ever return a single type it works fine.
    – john
    Aug 5, 2013 at 21:19

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .