Help comparing auto services to a filter list.

by grantc at 2013-04-01 03:12:51

Hi All,

I was wondering if anyone could help me…

I’m filtering out automatic services that are not running and comparing those to a list and then trying to output whats left.


$autoservices = Get-WmiObject Win32_Service
$ignoreservices = gc autoservicefilter.txt

PS> $ignoreservices
Software Protection
SomeFake Service


I can filter on startmode and state, but struggling to do so with DisplayName…


$autostopped = $autoservices | Where-Object { $.StartMode -eq ‘Auto’ -and $.State -ne ‘Running’} | where-object {$.DisplayName -notmatch $ignoreservices} | Select-Object Name, DisplayName, State, StartMode, StartName


I’ve also tried Where-Object { $
.StartMode -eq ‘Auto’ -and $.State -ne ‘Running’ -and $.DisplayName -notmatch $ignoreservices } but this isn’t working.
by Nobody at 2013-04-01 09:34:22
Try this

$autostopped = $autoservices | Where-Object { ($.StartMode -eq ‘Auto’) -and ($.State -ne ‘Running’) -and ($ignoreservices -notmatch “$($.DisplayName)")}| Select-Object Name, DisplayName, State, StartMode, StartName


edit:

I also think you should be doing somthing more like this.


$autostopped = get-wmiobject -query “SELECT * FROM WIN32_Service WHERE startmode = ‘auto’ AND state != ‘running’”| where-object {$ignoreservices -notmatch "$($
.DisplayName)”}|Select-Object Name, DisplayName, State, StartMode, StartName
by grantc at 2013-04-01 15:43:18
Thank you! That put me on the right path…

I’ve got it working now… The key was…

where-object {"$($ignoreservices)" -notmatch “$($.DisplayName)"}
by Nobody at 2013-04-01 21:14:46
[quote=“grantc”]Thank you! That put me on the right path…

I’ve got it working now… The key was…

where-object {"$($ignoreservices)" -notmatch "$($
.DisplayName)”}[/quote]

When you wrap a variable $(), you are merging all the array elements into a single string. It should work as the array object and compare each element to the pipline. In this case both ways might work for you, but it’s something to be aware of.

where-object {$ignoreservices -notmatch “$($.DisplayName)"}
by nohandle at 2013-04-02 02:21:24
[quote=“Nobody”]When you wrap a variable $(), you are merging all the array elements into a single string. [/quote]
This is not true but I see what you mean.
When you wrap array in subexpression nothing really happens, $(1,2)1
2

But if you wrap array in double quotes (mark it as expandable string), all of the array items are converted to string and merged into one string joined by value of $OFS (object field separator)
&{
#setting OFS to — in the current scope
$OFS = ‘—’
$arr = 1,2
“$arr”
}

1—2

Then there can be situation where you need to expand property of object in string like $
.DisplayName but the powershell parser by default expands just the name of the variable not the whole “property” call (”$service.name" results in <service object converted to string>.name"). so you need a way to tell the interpreter what should be expanded and that part you mark by the subespression “$($service.name)”.

So the subexpression mark does not affect the array, the quotes do.

I am covering my view on the topic here: http://powershell.cz/2012/12/19/subexpressions/ hope you find it useful.
by Nobody at 2013-04-02 09:37:24
Hey, thanks for that info. Good stuff! I kinda knew about subexpressions, but hadn’t quite put the pieces together. It’s all much clearer now. $OFS is new to me too!

I took a closer look at the match operation discussed in this post, and it appears the proper use here is to put the array variable in double quotes as that returns an actual boolean value. I understand the match operation a lot better now.

$a = @(“abc”,“def”,“ghi”,“123ghi456”)

$b = “$a” -match “ghi”
$c = $a -match “ghi”

"$b"
"$c"
by mjolinor at 2013-04-02 10:27:05
You might want to also investigate the -contains and -notcontains operators:

where-object {$ignoreservices -notcontians $_.DisplayName}
by nohandle at 2013-04-02 12:32:15
[quote=“Nobody”]I took a closer look at the match operation discussed in this post, and it appears the proper use here is to put the array variable in double quotes as that returns an actual boolean value. I understand the match operation a lot better now.[/quote]
hi you are partially right, there is lot more to it.
1) the match is used as such <string or array of strings> -match “string that represents regular expression pattern”
“name” -match “name”
“name” -match “na”
“name” -match "n[a-z]m[a-z]"

all return true because the pattern is valid and matches the string. (also look in the $matches variable after each match to see what matches and submatches were captured).

Regular expressions are something that whole book is not enough to fully describe, to utilize it in powershell make sure you know the basics and this “rule”: making regular expression that matches what you need is easy, making regular expression that matches only what you need is the hard part. :slight_smile:
I suggest you search bit more on it because there are numerous usages for the -match operator. Especially look up how the behavior changes with arrays of strings and also lookup named submatches, and lookaheads and lookbehinds).
by Nobody at 2013-04-02 14:00:01
I did reread about_Comparison_Operators this morning (for the umpteenth time) and discovered the $matches variable. Now for the submatches, lookaheads, and lookbehinds! Thanks (I think :slight_smile: )

I’ve fought quite a regex battles over the years, I don’t use complex regex expressions enough to know it well, but I like this site for helping me figure it out. http://rubular.com/
by MasterOfTheHat at 2013-04-03 06:42:04
Regular expressions are GREAT, if someone else writes them for me. I haven’t spend enough time with them to know them well, but that’s why we have the internet! I’ve used http://txt2re.com/index.php3 and http://www.regextester.com/ quite a bit, too.