Powershell Where-Object and DN exclusions - powershell

I am trying to query a list of users while excluding a specific OU. This is also using Quest's AD snap-in for Get-QADUser. I have this:
$ExcludedOU = "Service Accounts"
$inactiveUsers = Get-QADUser -SizeLimit 3 -SearchRoot $sourceOu -NotLoggedOnFor $InactiveFor -Enabled | Where-Object {$_.description -notlike $DescriptionPrefix -and #{n="ParentContainerDN";e={($_.ParentContainerDN -split ",*..=")[0]}} -notlike $ExcludedOU }
The goal is to exclude any users where the parent OU is "Service Accounts". ParentContainerDN looks like OU=Service Accounts,OU=Our Users,DC=DOMAINNAME,DC=ORG
This query does not error, but it does not exclude either. This is the part I may not have the syntax correct on?
#{n="ParentContainerDN";e={($_.ParentContainerDN -split ",*..=")[0]}} -notlike $ExcludedOU

I was partially wrong about the regex portion of your split. I am still correct in that the string supports regular expressions. That query will split on the CN=, OU= and DN=.
However you placed calculated property syntax into a where-object clause. It didn't error out since it is a valid hashtable and hashtables support like and notlike. Calculated properties are used for things like Format-Table and Select-Object which you can then reference those "new" properties later in other pipes.
$inactiveUsers = Get-QADUser -SizeLimit 3 -SearchRoot $sourceOu -NotLoggedOnFor $InactiveFor -Enabled |
Select-Obejct Name,SamAccountName,Description,#{n="ParentContainerDN";e={($_.ParentContainerDN -split ",*..=")[0]}} |
Where-Object {$_.description -notlike $DescriptionPrefix -and $_.ParentContainerDN -notlike $ExcludedOU }
The above syntax is what was also done in the code you linked to on Social Technet
I cannot make this return false for the life of me. This will evaluate to true which might be why your query was not working as expected. This is valid PowerShell just not correct to use.
#{n="ParentContainerDN";e={$_.WhatEver}} -notlike "string"
However like Kai Zhao mentioned in comments this is not really used effectively and you can get the same results without the calculated property.
$inactiveUsers = Get-QADUser -SizeLimit 3 -SearchRoot $sourceOu -NotLoggedOnFor $InactiveFor -Enabled |
Where-Object {$_.description -notlike $DescriptionPrefix -and ($_.ParentContainerDN -split ",*..=")[1] -notlike $ExcludedOU}

Related

I am trying to add members to a AD group based on a value in the "title" attribute

I am trying to add members to a AD group based on a value in the "title" attribute. I have about 30 different tiles i want to use. Is there a way to write the command witout 30 "OR" statements?
Thanks
Get-ADuser -filter {(title -eq "SECSCH") -or (title -eq "SEC12") -or (title -eq
"LTOSEC") -or (title -eq "LTO12")} | %{Add-ADGroupMember "SDK test print color"
$_.SamAccountName}
Also, for another group I would like All "custod" in title except at location "85c" and "42c" Below is where i am at.
Get-ADuser -filter {(title -eq "custod") -and (locationNumber -ne "85c") -or (title -eq
"custod") -and (locationNumber -ne "42c")} | %{Add-ADGroupMember "SDK test print
convert" $_.SamAccountName}
For your first issue you can create an array which contains your titles and browse it.
Example :
$Titles = "SECSCH","SEC12","LTOSEC","LTO12"
foreach($Title in $Titles){
Get-ADuser -filter {title -eq $Title} | %{Add-ADGroupMember "SDK test print color" $_.SamAccountName}
}
The -Members parameter can take an array of ADPrincipal objects so what you can do instead of using so many 'OR's in the Filter is using a Where-Object clause afterwards.
This will allow you to use operators like -contains or -match
$titles = "SECSCH","SEC12","LTOSEC","LTO12" # your 30+ titles here
$users = Get-ADUser -Filter * -Properties Title | Where-Object { $titles -contains $_.Title }
Add-ADGroupMember -Identity "SDK test print color" -Members $users
As for your second code change the Filter to below
$filter = "Title -eq 'custod' -and (locationNumber -ne '85c' -and locationNumber -ne '42c')"
$users = Get-ADUser -Filter $filter -Properties Title, locationNumber
Add-ADGroupMember -Identity "SDK test print convert" -Members $users
Note: the property locationNumber is AFAIK not a standard attribute in AD. Is that a custom property in your organization or do you perhaps mean something else like Division or EmployeeNumber ?
I provided a different answer to the first at the other place it was asked, using -Ldapfilter, but I feel #Onyx's answer here is probably more intuitive if you're not so comfortable with that. It's efficient in that you're only getting the objects you need, not grabbing every account out of AD and throwing away most of them.
To be honest, doing -Filter 'title -like "*"' would be better than nothing if you MUST use a Where clause.
For the second question (as described in the comments), the same applies with maybe building an LDAPfilter or #Onyx's method of creating an array for your customlocations and doing a Foreach through those.
Or again, at the very least, do -Filter '(employeeType -ne "student") -and (CustomLocation -like "*")' before the Where.

Get-ADUser with multiple filters & variables

I'm trying to get AD users into a variable using multiple filters. However one of the filters has variables in it & I can't get it to work... I have searched for similar issues & tried applying those but nothing seems to work.
$FilterBase = "department"
$Filter = "IT"
$ADusers = Get-ADUser -ResultSetSize $null -SearchBase "OU=Users,DC=mydomain,DC=com" -Properties * -Filter {(Enabled -eq $True) -and ($FilterBase -like $Filter) -and (cn -notlike ""SMB_*"")} |
Select-Object distinguishedName |
Sort-Object distinguishedName
I'm trying to fill $ADusers with all enabled users whose commonname doesn't start with "SMB_" (don't ask) & where the department is IT. I used -like to prevent issues if the values in AD would have different casings (uppercase, lowercase, mixed case, ...).
The reason that I'm using variables for this is because in the end the script will be dynamic. At some point $FilterBase is going to be "company" instead of "department" and $Filter is going to be "HR" instead of "IT" etc...
But I just can't seem to get it to work:
Get-ADUser : Error parsing query: '(Enabled -eq $True) -and ($FilterBase -like $Filter) -and (cn -notlike ""SMB_*"")' Error Message: 'syntax error' at position: '74'.
At line:4 char:12
I have tried using quotes around the variables like "$Filter", "$($Filter)", ' $Filter ' but alas. And I know it's not best practice to use variables in Filter but I can't think of any other way to accomplish this.
Any suggestions?
the error has the key to the answer. I'm sure I'll find this again and use it myself because I look this up every year or so...
Error parsing query: '(Enabled -eq $True)...'
In this case the filter needs a simple string 'True' which the variable $True does equal.
Two options will work, either
Enabled -eq 'True'
or
Enabled -eq '$True'
but
Enabled -eq $True
will not.
This should work
Replaced the braces with double quotes so inside them the variables still parse
Put single quotes around all strings and variables that resolve into strings
'$True'
'$Filter'
'SMB_*'
$FilterBase = "department"
$Filter = "IT"
$ADusers = Get-ADUser -ResultSetSize $null -SearchBase "OU=Users,DC=mydomain,DC=com" -Properties CN -Filter "(Enabled -eq '$True') -and ('$FilterBase' -like '$Filter') -and (CN -notlike 'SMB_*')" |
Select-Object distinguishedName |
Sort-Object distinguishedName
Important to note the above syntax highlighting will make the sample above look wrong because it misses the tokens like $FilterBase and $Filter when there are inside single quotes inside double quotes. Remember that single quotes are just apostrophes when inside double quotes, therefore the tokens should be colored differently and not look like strings.
> "('$FilterBase' -like '$Filter')"
('department' -like 'IT')
Paste a sample like above and see what it resolves to - best way to figure it out.
its just simply syntax error.
$enabled = 'Enabled'
$EnabledTrueOrFalse = $true
$SN = 'Surname'
$surname = "Doe"
$OU = "OU=Users,DC=mydomain,DC=com"
Get-ADuser -filter{$enabled -eq $EnabledTrueOrFalse -and $SN -eq $surname} -SearchBase $OU -Properties * | Select-Object distinguishedName | Sort-Object distinguishedName
read more about it here
Thanks for the tips guys. I couldn't get it to work with multiple filters so I moved some filters to the where clause.
My current (working) code is now:
$FilterBase = "department"
$Filter = "IT"
$ADusers = Get-ADUser -ResultSetSize $null -SearchBase "OU=Users,DC=mydomain,DC=com" -Properties * -Filter "$FilterBase -like `"$Filter`"" |
Where {$_.Enabled -eq $True -and $_.CN -notlike "SMB_*"} |
Select-Object distinguishedName |
Sort-Object distinguishedName

Search-ADAccount - This operation returned because the timeout period expired

I have the following code:
Search-ADAccount -AccountExpiring -TimeSpan "90" -ResultPageSize:100 -ErrorAction SilentlyContinue |
where {$_.samaccountname.StartsWith("X") -or $_.samaccountname.StartsWith("Y")} |
Select-Object samaccountname,Name,AccountExpirationDate |
Export-Csv $PSScriptRoot\Results\AD_Expiration_Dates_Accounts_Next_90_days_$((Get-Date).ToString('dd_MM_yyyy')).csv -NoTypeInformation -Append
I keep getting the error mentioned in the title with or without the -ResultPageSize: option.
The interesting thing is that when I change the -TimeSpan value I get more or less values and the data seems therefore to be coherent but, it always ends with the same error nevertheless.
The thing is, I'm not sure I can trust these values; even when I remove the option -ErrorAction SilentlyContinue I don't get any other error or information.
Does anyone have any input on this?
In this instance, it'd be way better to use Get-ADUser with a proper filter for all the criteria you want, rather than returning a whole lot of results and then using a where clause on them.
Also consider using the -searchbase option to limit which OU you search (if all the target accounts are in a specific OU).
$now = get-date
$90days = (get-date).adddays(90)
get-aduser -filter '(AccountExpirationDate -gt $now) -and (AccountExpirationDate -le $90days) -and (samAccountName -like "X*" -or sAMAccountName -like "Y*" )' -properties AccountExpirationDate
| Select-Object samaccountname,Name,AccountExpirationDate

Powershell to get accounts with passwords older than "$"

I am trying to get a list of accounts with passwords that are older than lets say 90 days but something is not working right and I am not sure why.
Get-ADUser -Filter 'Enabled -eq $True' -Properties PasswordLastSet,samaccountname,passwordlastset | Where-Object {$_.PasswordLastSet -gt ($_.PasswordLastSet).adddays(1)} | select Name,samaccountname,passwordlastset
This is what i got so far but if I run it as is it returns 0 results. I know there are passwords that are older than one day, mine is one of them. Any help is appreciated.
Per your realization in the comments you should compare the PasswordLastSet field to today's date less 90 days as follows:
Get-ADUser -Filter 'Enabled -eq $True' -Properties PasswordLastSet | Where-Object {$_.PasswordLastSet -lt (Get-Date).adddays(-90)} | select Name,SamAccountName,PasswordLastSet
Use -lt for older passwords, or -gt for newer passwords.
You can try this,if you wana export remove #
$DaysAgo=(Get-Date).AddDays(-90)
$params = #{
"filter" = 'Enabled -eq $true -and passwordlastset -lt $DaysAgo'
"Properties" = "Displayname",
"passwordlastset",
"samaccountname"
}
Get-ADUser #params |select displayname,samaccountname,passwordlastset #| export-csv C:\result.csv -nti

Powershell: where {_.Name not in $object}

I'm building a script that lists all Inactive computer accounts. I'd like to exclude a few systems from the results.
I've got a text-file containing all systems to be excluded (one systemname per line). All items are stored in an object with property name "name". So $excluded will contain:
name
----
system1
system2
To list all inactive systems I use the Search-ADAccount cmdlet:
$InactiveComputers = Search-ADAccount -AccountInactive -TimeSpan 90 -ComputersOnly | Where {$_.Enabled -eq $true}
Of course I can loop all results 1 by 1, but is there a simple way to exclude the systems directly from the results? I've got a feeling it's possible with select-object or where-object, but I can't figure out how to compare against the results in an object.
You were basically correct in using this in your title: "where {_.Name not in $object}"
Syntax is a little different. Pipe it to the following
Where { !($_.Name -in $excluded) }
OR
Where { $_.Name -notin $excluded }
Both seem to give the same results in the console. Happy coding!
Note: Tested this on PSv2 and v3.
I ran across this when looking for an answer and figured I would update with these options for others that run into this.
Import the exclude file (as csv) and use the -notcontains operator:
$names = Import-csv exclude.txt | Foreach-Object {$_.Name}
$InactiveComputers = Search-ADAccount -AccountInactive -TimeSpan 90 -ComputersOnly | Where {$_.Enabled -eq $true -and $names -notcontains $_.Name}
I think you can use -notcontains (TechNet article) operator:
$InactiveComputers = Search-ADAccount -AccountInactive -TimeSpan 90 -ComputersOnly | Where {$_.Enabled -eq $true -and $excluded -notcontains $_.name }