Question

How to use one PS dataset in a WHERE-OBJECT of another dataset

I have been using PS for about 10 years. Today I am stuck with finding a solution to a problem where I want to have items used in a WHERE-Object loaded from a SQL table. From what I have read, I need to build a filter object that builds the WHERE... -and clause, which I have rendering (to me) correctly, but when I attempt to apply that filter to the object it does absolutely no filtering, or it weirdly returns the WHERE clause for every record in the dataset. But when I paste the rendered $filter text, it does work, filtering out all records.

The dataset is populated from an OUTLOOK com object, and it is basically a list of emails that I want to filter. When I run the script with the filter variable, it doesnt filter anything, but when I manually past the rendered filter text, it appears to work: Results :

$dsResults = Get-OutlookInBox -cutoff $cutoff | select Subject, ReceivedTime, Importance, SenderName, body

#The below is how I am loading the exclusion list from SQL and building the $filter
$dsExclude = Select-SQL "SELECT Keyword = LTRIM(RTRIM(Keyword)) FROM Email_Mining_Keywords WHERE Action='Exclude' AND WordLocation='Subject'" -ConnectionStringOrSetting $DestConnectionString  

#The below filter does render correctly 
$filter = ($dsExclude | select -ExpandProperty KeyWord | % { "Subject -notlike '*$_*'" }) -join ' -and '


$dsResults | select -ExpandProperty subject |   ?{$filter} | Out-GridView `
#The results do not appear to filter anything (see image attachement)
[Results after filtering][1]

But it works when I past the rendered $filter:

$dsResults | ?{$_.Subject -notlike '*ENROLLMENT PACKAGE*' -and $_.Subject -notlike '*ENRPKG*' -and $_.Subject -notlike '*FW:*' -and $_.Subject -notlike '*FWD:*' -and $_.Subject -notlike '*RE:*' -and $_.Subject -notlike '*REPRINT*' -and $_.Subject -notlike '*RETURN*' -and $_.Subject -notlike '*UPDATED*'} | Out-GridView 

It took me a bit to understand that I needed to escape the pipeline object in front of the Subject in the $filter.

 2  36  2
1 Jan 1970

Solution

 2

$filter contains a synthesized piece of source code as a string.

Therefore, using {$filter}, i.e. referencing the variable in a script block literal ({ ... }) passed to Where-Object (one whose built-in aliases is ?), is always $true, because any nonempty string is coerced to $true in a Boolean context.

To get the desired behavior, you must construct your script block directly from your source-code string, using [scriptblock]::Create():

$filter = 
  [scriptblock]::Create(
    ($dsExclude | select -ExpandProperty KeyWord | % { "Subject -notlike '*$_*'" }) -join ' -and '
  )
2024-07-19
mklement0