0

I wrote the following pipe of commands:

get-process | where {$_.Path -notmatch ${env:SystemRoot} -and $_.Path -notmatch ${env:ProgramFiles} -and $_.Path -notmatch ${env:ProgramFiles(x86)} | select path, name

I got error:

parsing "C:\Program Files" - Malformed \p{X} character escape.
At line:1 char:22
+ get-process | where {$_.Path -notmatch $env:SystemRoot -and $_.Path -notmatch $e ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (:) [], ArgumentException
    + FullyQualifiedErrorId : System.ArgumentException

I understood what happened and I did several tests. I called Get-ChildItem cmdlet with paths with and without escape char. All work correctly. I put into Where-Object FilterScript parameter script block which had paths with and without "\" escape char. Where-Object with paths containing escape char worked correctly but when I put paths without escape char in Where-Object - I always get the error.

This isn't problem of system environment variables. I defined variable ProgramFilesA with "C:\Program Files" and variable ProgramFilesB with "C:\Program Files". When I use $env:ProgramFilesA in Where-Object I get error, when I use $env:ProgramFilesB all works fine.

How I should call standard $env: variables containing path in Where-Object cmdlet to run it without errors?

Matt
  • 45,022
  • 8
  • 78
  • 119

2 Answers2

0

You can use Regex escape.

The following should work:

get-process | where {$_.Path -notmatch [Regex]::escape($env:SystemRoot) -and $_.Path -notmatch [Regex]::escape(${env:ProgramFiles(x86)}) -and $_.Path -notmatch [Regex]::escape(${env:ProgramFiles(x86)}) } | select path, name

If you're trying to get the processes running which is not located within subfolders of program files and system root; you might want to modify your match expression for a wildcard (of any paths starting with).

Harald F.
  • 4,505
  • 24
  • 29
0

This issue is because you are using -match which is an operator that uses regular expressions and you are not escaping regex metacharacters properly. That is what the error was trying to tell you:

Malformed \p{X} character escape

The \p is the P in "Program files". \p in regex is used for matching code points.

You could just use -like instead. We use double quotes here to allow for variable expansion.

get-process | where {$_.Path -notlike "$($env:SystemRoot)*" -and $_.Path  -notlike "$($env:ProgramFiles)*" -and $_.Path -notlike "(${env:ProgramFiles(x86)})*"}

If you did want use regex might as well collect those environment variables and make a proper regex string with them.

$regex = "^(" + (($env:SystemRoot, $env:ProgramFiles, ${env:ProgramFiles(x86)} | ForEach-Object{[regex]::Escape($_)}) -join "|") + ")"
Get-Process | Where-Object {$_.Path -notmatch $regex}

So now the matching regex string is "^(C:\Windows|C:\Program\ Files|C:\Program\ Files\ (x86))"

Community
  • 1
  • 1
Matt
  • 45,022
  • 8
  • 78
  • 119
  • @JarosławWiechecki Just noticed I missed one of the asterisks in my like condition. FYI it has been fixed if you used that. – Matt Feb 23 '16 at 12:46