Often when you run a cmdlet you will get far more results than you can view. You will need to tell the cmdlet which particular ones you want and you can do this by filtering the returned values.
I think it is important here to recognise that you aren’t filtering what the cmdlet finds you are flittering results from what it found. This is the process:
Run cmdlet > pass output to filter > filter for just the bits we want
This means that it can take a long time to run some commands even though you only want a small subset of results.
Filtering is done by the Where-Object
cmdlet or its Alias Where
get-service
will return every service installed regardless of it’s status. In my lab this returned 254 services, but what if we only want to see what has started
get-service | where-object -property status -eq running
This reduced the number to 102
What else can we filter on. Remember get-member
? We can use this to see all the properties and we can choose to filter on any of them
get-service | get-member
I can see a StartType property, let’s see if we can look at services that aren’t set to autostart
get-service | where-object -property starttype -ne automatic
well that worked but I got 194 services returned in various states and some are started, so how can we find those that are started but not automatically? The answer to this is to replace the -Property parameter with -FilterScript and then put our query into a script block like this:
get-service | where-object -FilterScript {($_.Starttype -ne automatic) -and ($_.status -eq running)}
what we have done here is to tell the script that we want to check each record for its start type and its current status
and finally if we want to see the start type we would need to tell it to include that in the output
get-service | where-object -FilterScript {($_.Starttype -ne automatic) -and ($_.status -eq running)} | select Status, Name, Displayname, StartType
Filtering Left
Remember when I said we should do as much as we can in the cmdlet and pipe the smallest number of result to the pipeline, what did I mean by that? Consider this simple example:
get-service | where name -like "*bits*"
this returns exactly what you would expect, but to do that its has found all services and then piped that list in where-object which has then re-processed the list to find the one named BITS. It doesn’t take long in this example but we can ask the cdmlet to do that for us without the pipe
get-service -servicename 'BITS'
it returns the same results but faster … let me demonstrate this by measuring the time it takes to complete
Using the Measure-Command
I can demonstrate that the filter took longer. In this case it is only milliseconds, but a larger query with more records can be significantly impacted as can the computer it runs on.
Summary
Try to find exactly what you want using cmdlet parameters first.
If that fails you can pipe results in where-object and use either the -Property
or -FilterScript
parameters to reduce the returned values to a manageable number.