Adam
Adam

Reputation: 243

Issues filtering based on description

I am having issues filtering out accounts in a Search-ADAccount query. The query always returns the 40 days inactive AD accounts that are enabled and have logged in at least once. However a number of accounts being returned are flagged as long-term sickness, maternity leavers or are Helpdesk accounts. In the users' objects the keyword will appear at least once, hence my use of -notlike to have the wildcard function. But it still does not work, any ideas are much appreciated!

$excludelist = "Sickness", "Maternity", "Helpdesk"
$users = Search-ADAccount -AccountInactive -TimeSpan (New-TimeSpan -Days 40) -Searchbase "OU=Users,OU=State,DC=Company,DC=Biz" |
         where {($_.enabled -eq $true) -and
                ($_.Description -notlike $excludelist) -and
                ($_.LastLogonDate -notlike $null) } |
         Get-ADUser -Properties mail, manager, LastLogonTimeStamp

UPDATE: Based off the help in the comments, I have updated the code however the filtering does not apply. Here is the full code;

Import-Module ActiveDirectory

#Set our non-changing variables for the email
$SMTPServer = "[email protected]"
$From = "Helpdesk <[email protected]>"

#Set Testing if needed
$testing = "Enabled" #Set to disabled to go live
$testRecipient = "[email protected]"

#Set Description Modifiers:
$excludelist = 'Sickness|Maternity|Helpdesk'

#Query AD for all the NCE accounts with no activity for 40 days and are enabled
$users = Search-ADAccount -AccountInactive -TimeSpan (New-TimeSpan -Days 40) -Searchbase "OU=Users,OU=Company,DC=Company,DC=de" | 
Where-Object {
    $_.Enabled -and
    $_.Description -notmatch $excludelist -and
    $_.LastLogonDate
} | Get-ADUser -Properties mail, manager, LastLogonTimeStamp, description

#Loop through the query results
foreach ($User in $Users) {
    #Convert LastLogonDate to days since last use
    $lastLogon = [DateTime]::FromFileTime($User.lastLogonTimeStamp)
    $Daysinactive = ((Get-Date) - $lastLogon).Days

    #Get manager email with passthrough
    $Manager = Get-ADUser $User.Manager -Properties EmailAddress

    #Set dynamic variables and body of email
    $To = $Manager.EmailAddress
    $Subject = "Your employee $($User.Givenname) $($User.Surname) has not been active since $Daysinactive days."
    $Body = 
    "Hello $($Manager.GivenName),<br>
<p>The account of $($User.Givenname) $($User.Surname) has not been active for $Daysinactive days. Please explain in return email.
<table border='1'>
<tr>
<td>Name</td>
<td>eIPN</td>
<td>email</td>
<td>Inactive Days</td>
<td>Description</td>
<td>Test</td>
</tr>
<tr>
<td>$($User.Givenname) $($User.Surname)</td>
<td>$($User.SamAccountName)</td>        
<td>$($User.mail)</td>
<td>$Daysinactive</td>
<td>$($User.Description)</td>
<td>$excludelist</td>
</tr>
</table>
<p>Thanks you.<br>
<p>IT Helpdesk"

    #Testing check before email is sent
    if (($testing) -eq "Enabled") {
        $To = $testRecipient
    } # End Testing

    #Send email
    Send-MailMessage -To $To -From $From -Subject $Subject -SmtpServer $SMTPServer -Body $Body -BodyAsHtml -Priority High
}

To test, I have added in the $($User.Description) and $excludelist into the email table to ensure that the values are being read.

A user that should be filtered is returning a table such as thus:

enter image description here

So I can see that user.description is being read with the excluded word "Helpdesk" in it, but it does not filter.

I have also tried to set the $exludelist to simply "Helpdesk" but that does not filter either.

Any help is appreciated. I have tried every method of writing the filtering method I can find online but still no luck!

Upvotes: 1

Views: 180

Answers (2)

Ansgar Wiechers
Ansgar Wiechers

Reputation: 200233

A condition <value> -notlike <list> won't work. The -notlike operator (as well as the -like operator) can only compare a value to another value with a wildcard pattern. Also, you only want items that have neither of the given strings in the description, so you'd have to define the filter like this:

Where-Object {
  $descr = $_.Description
  -not ($excludelist | Where-Object {$descr -like "*$_*"})
}

If you want to check whether an attribute doesn't contain any of a given list of strings it's simpler to use a regular expression and the -notmatch operator. Also, the properties of the objects returned by Search-ADAccount don't include the attribute description, so you can't filter on that property before running Get-ADUser (which you must instruct to fetch that attribute). Another thing you may want to do is add the parameter -UsersOnly to Search-ADAccount to prevent it from fetching computer accounts and the like.

Change your code to this:

$excludelist = 'Sickness|Maternity|Helpdesk'
$users = Search-ADAccount ... -UsersOnly |
         Where-Object { $_.Enabled -and $_.LastLogonDate } |
         Get-ADUser -Properties mail, manager, LastLogonTimeStamp, Description |
         Where-Object { $_.Description -notmatch $excludelist }

Upvotes: 1

Mathias R. Jessen
Mathias R. Jessen

Reputation: 174485

The -like operator(s) doesn't work well with an array as its right hand argument:

PS C:\> "a" -notlike "a","b"
True

Since -like (or any variation, including -notlike) expects a string on the right hand, it converts the array to a single string and so your filter effectively becomes:

$_.Description -notlike "Sickness Maternity Helpdesk"

I doubt this will ever exclude anyone :)


You can use the -contains operator instead:

$excludelist -notcontains $_.Description

Or the -in operator (PowerShell 3.0 or newer):

$_.Description -notin $excludelist

Upvotes: 0

Related Questions