The Big Book of PowerShell Gotchas
  • ReadMe
  • About this Book
  • Format Right
  • Where is the __ command?
  • PowerShell.exe isn't PowerShell
  • Accumulating Output in a Function
  • ForEach vs ForEach vs ForEach
  • Tab Complete!
  • -Contains isn't -Like
  • You Can't Have What You Don't Have
  • Filter Values Diversity
  • Not Everything Produces Output
  • One HTML Page at a Time, Please
  • Bloody. Awful. Punctuation.
  • Don't Concatenate Strings
  • $ Isn't Part of the Variable Name
  • Use the Pipeline, Not an Array
  • Backtick, Grave Accent, Escape
  • These Aren't Your Father's Commands
  • A Crowd isn't an Individual
  • Commands' Default Output Can Lie
  • Properties vs. Values
  • Remote Variables
  • New-Object PSObject vs. PSCustomObject
  • Running Something as the "Currently Logged-in User"
  • Commands that Need a User Profile May Fail When Run Remotely
  • Writing to SQL Server
  • Getting Folder Sizes
Powered by GitBook
On this page

-Contains isn't -Like

PreviousTab Complete!NextYou Can't Have What You Don't Have

Last updated 7 years ago

Oh, if I had a nickel for every time I've seen this:

I get how this happens. The -contains operator seems like it should be checking to see if a process' name contains the letters "notepad." But that isn't what it does.

The correct approach is to use the -like operator, which in fact does do a wildcard string comparison:

I'll let pass the thought that the really correct answer is to just run Stop-Process -name *notepad*, because I was aiming for a simple example here. But... don't overthink things. Sometimes a script and a ForEach loop isn't the best approach.

So anyway, what does -contains (and its friend, -notcontains) actually do? They're similar to the -in and -notin operators introduced in PowerShell v3, and those operators cause more than a bit of confusion, too. What they do is check to see if a collection of objects contains a given single object. For example:

In fact, that example is probably the best way to see it work. The trick is that, when you use a complex object instead of a simple value (as I did in that example), -contains and -in look at every property of the object to make a match. If you think about something like a process, they're always changing. From moment to moment, a process' CPU and memory, for example, are different.

In this example, I've started Notepad. I've put its process object into $single_proc, and you can see that I verified it was there. But when I run Get-Process and check to see if its collection contained my Notepad, I got False. That's because the object in $single_proc is out of date. Notepad is running, but it now looks different, so -contains can't find the match.

The -in and -contains operators are best with simple values, or with objects that don't have constantly-changing property values. But they're not wild card string matching operators. Use -like (or -notlike) for that.

image015.png
image017.png
image019.png
image021.png