PowerShell "-notlike" comparison is not working with wildcard - powershell

I'm trying to filter out various user accounts in PowerShell (using the NTFSSecurity module) and it's not working as completely as expected. It is supposed to get an array of $users except for the following conditions:
$users = Get-NTFSAccess $path | Where-Object {
$_.Account -ne "DOMAIN\Domain Admins" -and
$_.Account -ne "Group1" -and
$_.Account -ne "Group2" -and
$_.Account -notlike "SecProj_*" -and
$_.Account -notlike "GRP_SECURE_*"
}
The script filtering out DOMAIN\Domain Admins, Group1, and Group2. These groups are defined directly by name.
The script is NOT filtering out SecProj_* and GRP_SECURE_*.
Am I using the wildcard (*) correctly in the -notlike statement?

Related

read the value from registry rather than hard code in if statement

i have below powershell line. It will return 1 when there is account found in administrators group other than built-in administrator, group1, group2, group3.
If ((Get-LocalGroupMember -Group Administrators | Where-Object {($_.ObjectClass -eq 'User' -or $_.ObjectClass -eq 'Group') -and (($_.Name -notlike "$env:computername\administrator") -and ($_.Name -notlike 'group1') -and ($_.Name -notlike 'group2') -and ($_.Name -notlike 'group3') )}).Count -gt 0) {
echo 1
}else{
echo 0
}
how do i change the above if statement to read in the string value (which has commas) in registry so I don’t need to hard code group1, group2, group3 in the if statement?? Thanks
example i had set it at hklm:\system\test , named as adm and string value of group1,group2,group3
i am able to pull the value i set at registry using this line.
$listofadm = (Get-ItemProperty -Path "HKLM:\system\test" -ErrorAction Stop -Name adm).adm
Not sure why you are checking if user or group, if you can omit that it will simplify your check. To streamline this I would make a regex pattern of all the groups including the computer\adminsitrator account. If the groups indeed do not have a space then you can simply replace the commas with a pipe | character.
$listofadm = "$env:computername\administrator|" +
(Get-ItemProperty -Path "HKLM:\system\test" -ErrorAction Stop -Name adm).adm -replace ',','|'
This will make $listofadm contain something like
DESKTOP-NEKK74J\administrator|group1|group2|group3
Now if you just want to find any object whose name is not any of those 4
Get-LocalGroupMember -Group Administrators | where name -NotMatch $listofadm
Single item checks in the Where clause can omit the { } curly braces. If you do need to ensure it's a user or group object then this is how that would look.
Get-LocalGroupMember -Group Administrators |
Where-Object {($_.ObjectClass -eq 'User' -or $_.ObjectClass -eq 'Group') -and $_.name -NotMatch $listofadm}

Exchange online, New-DynamicDistributionGroup with phone number

I'm trying to create a DDG with powershell that returns all users that have mobile phone.
I've checked which propireties are filtrable and I've created the group with:
New-DynamicDistributionGroup -Name "Groupname" -RecipientFilter "(RecipientType -eq 'UserMailbox') -and (Phone -ne '$null')"
And the group gets created successfully, but when I try to see the user in group with the command below I get this error:
$FTE = Get-DynamicDistributionGroup "GroupName"
Get-Recipient -RecipientPreviewFilter $FTE.RecipientFilter -OrganizationalUnit $FTE.RecipientContainer
The recipient preview filter string "((Phone -ne '') -and (-not(Name -like 'SystemMailbox{*')) -and (-not(Name -like 'CAS_{*')) -and (-not(RecipientTypeDetailsValue
-eq 'MailboxPlan')) -and (-not(RecipientTypeDetailsValue -eq 'DiscoveryMailbox')) -and (-not(RecipientTypeDetailsValue -eq 'PublicFolderMailbox')) -and
(-not(RecipientTypeDetailsValue -eq 'ArbitrationMailbox')) -and (-not(RecipientTypeDetailsValue -eq 'AuditLogMailbox')) -and (-not(RecipientTypeDetailsValue -eq
'AuxAuditLogMailbox')) -and (-not(RecipientTypeDetailsValue -eq 'SupervisoryReviewPolicyMailbox')))" is neither a valid OPath filter nor a valid LDAP filter. Use the
-RecipientPreviewFilter parameter with either a valid OPath filter string or a valid LDAP filter string.
all the other filter string are created automatically buy exchange I guess, what could be the issue?
Thank you for your help.

Multiple condition in where clause

When I execute below code, I get an error as : A parameter cannot be found that matches name or. How can I get user list who don't have abc.com or xyz.com in their email address?
Get-ADGroupMember -Identity "AQ" -Recursive | where objectClass -eq 'user' | Get-ADUser -Properties *, "msDS-UserPasswordExpiryTimeComputed", PasswordNeverExpires |
where mail -notmatch "#abc.com" -or "#xyz.com" |
Select-Object #{Label = "SAM Account Name";Expression = {$_.SamAccountName}}
The curly braces (actually a scriptblock with the filter script) can not always be skipped with Where-Object.
You can do Where-Object objectClass -eq 'user' but everything that involves more than a single operator requires to be written as a filter script:
where {$_.mail -notmatch "#abc.com" -or "#xyz.com" }
Now this logic doesn't work, as this is equivalent to the following statement:
where {($_.mail -notmatch "#abc.com") -or $true }
So your where clause is true, regardless of the result of the -notmatch operation. You want two -notmatch operations instead:
Where-Object - { $_.Mail -notmatch '#abc.com' -and $_.Mail -notmatch '#xyz.com' }
Depending on the amount of email addresses, that you want to exclude in your filter script, you might want to use a different approach: Strip the user name from the email address and see, if this address appears in the array of email addresses that you want to exclude.
Where-Object { ( $_.Mail -replace '^[^#]+') -notin '#abc.com','#xyz.com','#foo.bar' }
for multiple conditions use full syntax:
where-object { $_.property -eq $b -and $_.otherproperty -match $a }
You're missing some brackets around your where-clause:
where {objectClass -eq 'user'}
And this:
where {mail -notmatch "#abc.com" -or "#xyz.com"}
Should look like that:
where {mail -notmatch "#abc.com" -or mail -notmatch "#xyz.com"}
Please rethink the logic of your second where since it will always be true.

Powershell Scripts inconsistent behavior

I have two powershell scripts that revolve around abandoned accounts. These scripts should exclude six specific OUs in our environment. The first reports all accounts that will require action. The second takes action and disables the accounts based on the same criteria.
For reasons I can't figure out, the disable script is leaving behind users across multiple OUs that it is not taking action on. Any help at all will be appreciated.
Here's the reporting version:
import-module activedirectory
$datestring = Get-Date -f MM-dd-yyyy
$oldDate = [DateTime]::Today.AddDays(-45)
$OUDN1 = "OU=Resource accounts,OU=Domain Users,DC=placeholder,DC=org"
$OUDN2 = "OU=Service Accounts,OU=Domain Users,DC=placeholder,DC=org"
$OUDN3 = "OU=DO NOT DELETE,OU=Disabled Accounts,DC=placeholder,DC=org"
$OUDN4 = "CN=Users,DC=placeholder,DC=org"
$OUDN5 = "OU=User Templates,OU=Domain Users,DC=placeholder,DC=org"
$OUDN6 = "CN=Microsoft Exchange System Objects,DC=placeholder,DC=org"
Get-ADUser -filter {(Enabled -eq $True) -AND ((LastLogonDate -lt $olddate) -OR ((LastLogonDate -notlike "*") -AND (WhenCreated -lt $olddate)))} -Properties DisplayName,Name,LastLogonDate,Modified,info,description,sAMAccountName,WhenCreated | Where-Object {($_.DistinguishedName -notlike "*,$OUDN1") -and ($_.DistinguishedName -notlike "*,$OUDN2") -and ($_.DistinguishedName -notlike "*,$OUDN3")-and ($_.DistinguishedName -notlike "*,$OUDN4") -and ($_.DistinguishedName -notlike "*,$OUDN5") -and ($_.DistinguishedName -notlike "*,$OUDN6")} | Select sAMAccountName,Name,description,LastLogonDate,WhenCreated,Modified,DistinguishedName | Export-CSV c:\Reports\nolog45_$datestring.csv
And here's the action version:
import-module activedirectory
$disUsers = #()
$oldDate = [DateTime]::Today.AddDays(-45)
$OUDN1 = "OU=Resource accounts,OU=Domain Users,DC=placeholder,DC=org"
$OUDN2 = "OU=Service Accounts,OU=Domain Users,DC=placeholder,DC=org"
$OUDN3 = "OU=DO NOT DELETE,OU=Disabled Accounts,DC=placeholder,DC=org"
$OUDN4 = "CN=Users,DC=placeholder,DC=org"
$OUDN5 = "OU=User Templates,OU=Domain Users,DC=placeholder,DC=org"
$OUDN6 = "CN=Microsoft Exchange System Objects,DC=placeholder,DC=org"
$disUsers = Get-ADUser -filter {(Enabled -eq $True) -AND (LastLogonDate -lt $olddate)} -Properties sAMAccountName,Name,SID,Enabled,LastLogonDate,Modified,info,description,DistinguishedName | Where-Object {($_.DistinguishedName -notlike "*,$OUDN1") -and ($_.DistinguishedName -notlike "*,$OUDN2") -and ($_.DistinguishedName -notlike "*,$OUDN3")-and ($_.DistinguishedName -notlike "*,$OUDN4") -and ($_.DistinguishedName -notlike "*,$OUDN5") -and ($_.DistinguishedName -notlike "*,$OUDN6")}
foreach ($name in $disUsers) {
$DistName = $name.DistinguishedName
Disable-ADAccount -Identity $DistName -ErrorAction Continue
}
Today's run for example left 30 accounts that the report script found still enabled. It wasn't permissions, because I could disable the same accounts manually with no problems. No red text was generated, no error output - just seemingly ignored the accounts.
Thanks in advance for your help.
The criteria in both scripts is not the same.
Your reporting script has this, which your action script does not:
-OR ((LastLogonDate -notlike "*") -AND (WhenCreated -lt $olddate))

Filter a few computers before exporting from pipeline

I need to filter out 4 machines prior to exporting to a csv file. I have no clue how to filter them out. I tried the IF clause but this produced nothing. Please help.
$old = (Get-Date).AddDays(-90) # Modify the -90 to match your threshold
$oldComputers = Get-ADComputer -SearchBase "OU=Workstations,DC=Corporate,DC=Local" -SearchScope 2 -Filter { PasswordLastSet -le $old } -Properties *
$oldComputers
if ($_.name -notlike "1919DD" -or $_.name -notlike "1919SMAHESHWARE" -or $_.name -notlike "1919IETEST" -or $_.name -notlike "1920BPASCERITB") {
Export-Csv c:\temp\Over90DaysMachines.csv -NoTypeInformation -Force -Append
}
For one thing, to be able to use the current object variable ($_) you need a pipeline context. Simply putting an if statement after echoing a variable doesn't automagically feed the echoed value(s) into the if statement. You need to change this:
$oldComputers
if ($_.Name -notlike "1919DD" -or ...) {
Export-Csv c:\temp\Over90DaysMachines.csv -NoTypeInformation -Force -Append
}
into something like this:
$oldComputers | Where-Object {
$_.Name -notlike "1919DD" -or ...
} | Export-Csv c:\temp\Over90DaysMachines.csv -NoType -Force
However, even with that change your filter won't work correctly, because you connected the -notlike clauses via -or when you should have used -and. You obviously meant to process objects only if their name doesn't match any of the given values. But for your logical expression to evaluate to $false the name would have to match all of the reference value at the same time. Which clearly isn't possible, thus your expression always evaluates to $true.
Example:
Assume that you have a variable $v that should not be equal to either A, B, or C. Applying your logic, the expression would look somewhat like this in PowerShell:
($v -notlike 'A') -or ($v -notlike 'B') -or ($v -notlike 'C')
If $v takes for instance the value A that expression becomes
('A' -notlike 'A') -or ('A' -notlike 'B') -or ('A' -notlike 'C')
⇔ ($false) -or ($true) -or ($true)
⇔ $true
To check if a give value equals neither of the reference values you need to connect the clauses via -and:
('A' -notlike 'A') -and ('A' -notlike 'B') -and ('A' -notlike 'C')
⇔ ($false) -and ($true) -and ($true)
⇔ $false
$oldComputers | Where-Object {
$_.Name -notlike "1919DD" -and
$_.Name -notlike "1919SMAHESHWARE" -and
$_.Name -notlike "1919IETEST" -and
$_.Name -notlike "1920BPASCERITB"
} | Export-Csv c:\temp\Over90DaysMachines.csv -NoType -Force
Note BTW, that the -notlike operator behaves exactly like the -ne operator when the reference string doesn't contain wildcard characters. If you're not doing fuzzy matches anyway you could simplify your expression by checking if the given name is (not) found in an array of names instead of doing multiple checks for (in)equality:
$excludes = '1919DD', '1919SMAHESHWARE', '1919IETEST', '1920BPASCERITB'
$oldComputers | Where-Object {
$excludes -notcontains $_.Name
} | Export-Csv c:\temp\Over90DaysMachines.csv -NoType -Force
Another option would be a regular expression (non-)match:
$oldComputers | Where-Object {
$_.Name -notmatch '^1919DD|1919SMAHESHWARE|1919IETEST|1920BPASCERITB$'
} | Export-Csv c:\temp\Over90DaysMachines.csv -NoType -Force
I'm guessing the code in the OP is a fragment from a larger script. Presumably it is the body or part of the body of a ForEach-Object. (If not then $_ doesn't make sense in this context). However a ForEach-Object isn't necessary. You can filter out the unwanted computers as follows:
$old = (Get-Date).AddDays(-90) # Modify the -90 to match your threshold
$oldComputers = Get-ADComputer -SearchBase "OU=Workstations,DC=Corporate,DC=Local" -SearchScope 2 -Filter { PasswordLastSet -le $old } -Properties *
$oldComputers | Where-Object {
$_.name -notin "1919SMAHESHWARE","1919IETEST", "1920BPASCERITB"
} | Export-Csv c:\temp\Over90DaysMachines.csv -NoTypeInformation -Force -Append
This assumes that $oldComputers is an array of object where each object has a property name and the value of name is a string like "server1", "server2", etc. The script in the OP outputs $oldComputers so verify it looks like a set of objects, with a name property consisting of a string where the servers to be excluded are spelled exactly as listed in the OP.
Please try below code
$old = (Get-Date).AddDays(-90) # Modify the -90 to match your threshold
$oldComputers = Get-ADComputer -searchbase "OU=Workstations,DC=Corporate,DC=Local" -SearchScope 2 -Filter { PasswordLastSet -le $old } -Properties *
$oldComputers = $oldComputers | where {$_.name -notlike "1919DD"
` -or $_.name -notlike "1919SMAHESHWARE"
` -or $_.name -notlike "1919IETEST"
` -or $_.name -notlike "1920BPASCERITB"}
Export-Csv c:\temp\Over90DaysMachines.csv -NoTypeInformation -force -append