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))
Related
I'm trying to write a script that will log out users which don't have specific process running in their session.
I guess the workflow should look like:
Get usernames of all the users logged in, get list of all the processes runnning on the workstation, check if X process is running for Y user, if not, then log user Y out.
So far i managed to create object with all the users currently logged in:
((quser) -replace '^>', '') -replace '\s{2,}', ',' | ConvertFrom-Csv
And list of all the processes running with usernames:
get-process -IncludeUserName
I believe foreach with if inside should do the job, but I can't quite get my head around it. I would appreciate any help.
Thanks!
edit:
$process = get-process -IncludeUserName|Where-Object{
($_.ProcessName -Like "processIneed1*") -or
($_.ProcessName -Like "processIneed2*") -or
($_.ProcessName -Like "processIneed") -or
($_.ProcessName -like 'processIneed3*') -and
($_.username -notlike '*userIwantToSkip1*') -and
($_.username -notlike '*userIwantToSkip2*')
}
$users = Get-RDUserSession | Where-Object -Property UserName -NE 'administrator'
$ActiveUsers = $users.username
foreach ($ProcUser in $process.username){
foreach ($ActiveUser in $ActiveUsers){
if ($ProcUser -like "*$ActiveUser*"){
$ActiveUsers = $ActiveUsers -notlike "*$ActiveUser*"
}
}
}
in $activeusers we are left with inactive users.
I will most likely change username to session ID and check it this way.
Next step will be logging off disconnected users.
$process = get-process -IncludeUserName|Where-Object{
($_.ProcessName -Like "processIneed1*") -or
($_.ProcessName -Like "processIneed2*") -or
($_.ProcessName -Like "processIneed") -or
($_.ProcessName -like 'processIneed3*') -and
($_.username -notlike '*userIwantToSkip1*') -and
($_.username -notlike '*userIwantToSkip2*')
}
$users = Get-RDUserSession | Where-Object -Property UserName -NE 'administrator'
$ActiveUsers = $users.username
foreach ($ProcUser in $process.username){
foreach ($ActiveUser in $ActiveUsers){
if ($ProcUser -like "*$ActiveUser*"){
$ActiveUsers = $ActiveUsers -notlike "*$ActiveUser*"
}
}
}
foreach ($inactiveusers in $ActiveUsers){
logoff $inactiveuser
}
Forgive me in advance as I may not be defining things correctly here:
I have a script that queries Active Directory for users in a specific OU while excluding a dozen or so OUs within that OU. The script works, but it's kind of messy as I'm declaring 13 variables representing the various OUs and referencing them in where-object. There's also an existing foreach loop as I'm querying more than one domain. I'd like to find a way to reference all the OU's I'm excluding from the query in a single collection or array or whatever and loop through it in my where-object to avoid having to reference 13 variables in the where-object. Can anyone point me in the right direction? (Code below excludes the OU variable defintions)
Existing Code:
(Get-ADForest).domains | foreach {
Get-ADUser -filter {Enabled -eq $True} -properties * -SearchBase "OU=Accounts,$((Get-ADDomain -Server $_).DistinguishedName)" -Server $_ |
where-object {$_.Title -notmatch "Volunteer" -and $_.DistinguishedName -notmatch $excludeOU1 -and $_.DistinguishedName -notmatch $excludeOU1 -and $_.DistinguishedName -notmatch $excludeOU2 -and
$_.DistinguishedName -notmatch $excludeOU3 -and $_.DistinguishedName -notmatch $excludeOU4 -and $_.DistinguishedName -notmatch $excludeOU5 -and $_.DistinguishedName -notmatch $excludeOU6 -and
$_.DistinguishedName -notmatch $excludeOU7 -and $_.DistinguishedName -notmatch $excludeOU8 -and $_.DistinguishedName -notmatch $excludeOU9 -and $_.DistinguishedName -notmatch $excludeOU10 -and
$_.DistinguishedName -notmatch $excludeOU11 -and $_.DistinguishedName -notmatch $excludeOU12 -and $_.DistinguishedName -notmatch $excludeOU13 }
}
Thanks!
You could use a regex to use with notmatch.
[regex]$excluderegex = "^(excludeOU1|excludeOU2|excludeOU3)$"
(Get-ADForest).domains | foreach {
Get-ADUser -filter {Enabled -eq $True} -properties * -SearchBase "OU=Accounts,$((Get-ADDomain -Server $_).DistinguishedName)" -Server $_ |
where-object {$_.Title -notmatch "Volunteer" -and $_.DistinguishedName -notmatch $excluderegex}
}
You can put anything you like inside the Where filter expression:
$excludes = $excludeOU1,$excludeOU2,$excludeOU3,$excludeOU4,$excludeOU5,$excludeOU6,$excludeOU7,$excludeOU8,$excludeOU9,$excludeOU10,$excludeOU11,$excludeOU12,$excludeOU13
Get-ADUser -Filter {Enabled -eq $true} -Properties * -SearchBase "OU=Accounts,$((Get-ADDomain -Server $_).DistinguishedName)" -Server $_ | Where-Object {
$_.Title -notmatch 'Volunteer' -and $(&{
foreach($exclude in $excludes)
{
if($_.DistinguishedName -match $exclude)
{
return $false
}
}
return $true
})
}
You could use the Select-Object cmdlet in your pipeline to add a new "calculated property" to your Get-ADUser data that holds just the OU of the user. The Where-Object call could then simply use a -notin operator.
In my opinion, this would make the code a little more readable. More info here:
Select-Object Calculated Properties
Notin Operator
Could some one tell me the issues with the query.
I want to pull back all the users that are not in a number of specific OU, I thought the following query would work, but as you can see it pulls back a user with "ou=staff" in the DN (extracted from all of the output).
I am trying to say if non of the following appear in the DN attribute.
$NotinDirectory = Get-ADObject -LDAPFilter "objectClass=person" -SearchBase "OU=Accounts,DC=Company,DC=ac,DC=uk" -Properties ou |? {($_.DistinguishedName -notlike "*Agency*" -and "*Contractors*" -and "*Fellows*" -and "*Visitors*" -and "*ou=Staff*" -and "*Contacts*")}
CN=jo blogs,OU=Staff,OU=Accounts,DC=compnay,DC=ac,DC=uk
UPDATE
so I tried this based on comments bellow
$NotinDirectory = Get-ADObject -LDAPFilter "objectClass=person" -SearchBase "OU=Accounts,OU=iah,DC=iah,DC=ac,DC=uk" | ? {($_DistinguishedName -notlike "*Agency*" -and $_DistinguishedName -notlike "*Contractors*" -and $_DistinguishedName -notlike "*Fellows*" ) -and ($_DistinguishedName -notlike"*Visitors*") -and ($_DistinguishedName -notlike"*OU=Staff*" -and $_DistinguishedName -notlike"*Contacts*")}
foreach ($test in $NotinDirectory){ Write-Host $test.DistinguishedName}
but i still get
CN=xxx xxxxx,OU=Staff,OU=Accounts,DC=company,DC=ac,DC=uk
In your Where-Object filter:
($_.DistinguishedName -notlike "*Agency*" -and "*Contractors*" -and "*Fellows*" -and "*Visitors*" -and "*ou=Staff*" -and "*Contacts*")
you only compare $_.DistinguishedName to a string once, the first time (-notlike "*Agency*").
It will be parsed as follows:
(($_.DistinguishedName -notlike "*Agency*") -and ("*Contractors*") -and ("*Fellows*") -and ("*Visitors*") -and ("*ou=Staff*") -and ("*Contacts*"))
(($_.DistinguishedName -notlike "*Agency*") -and $true -and $true -and $true -and $true -and $true)
($_.DistinguishedName -notlike "*Agency*")
You'll have to do:
Get-ADObject | Where-Object {($_.DistinguishedName -notlike "*Agency*" -and
$_.DistinguishedName -notlike "*Contractors*" -and
$_.DistinguishedName -notlike "*Fellows*" -and
$_.DistinguishedName -notlike "*Visitors*" -and
$_.DistinguishedName -notlike "*ou=Staff*" -and
$_.DistinguishedName -notlike "*Contacts*")}
in order to test for all 6 strings.
If you have a variable number of strings you want to exclude, you can use ForEach-Object inside Where-Object:
$Excludes = "*Agency*","*Contractors*","*Fellows*","*Visitors*","*ou=Staff*","*Contacts*"
Get-ADObject |Where-Object {
$ADObj = $_
#($Excludes |ForEach-Object {
$ADObj.DistinguishedName -notlike $_
}) -notcontains $false
}
I want to get all computers in my domain that are enabled, and have 2003 operating system, and the name of the computers do Not contain ' ping , pict , pire '
Here is what I have, but totally failing:
Get-ADComputer -filter {(Enabled -eq $True) -and (OperatingSystem -like "*2003*")} -properties OperatingSystem | where {($_.Name -notlike 'PING*') -or ($_.Name -notlike 'PICT*') -or ($_.Name -notlike 'PIRE*')} | Select Name
You can use the -notlike operator inside the filter, so there is no need for the where statement. See the Get-ADComputer reference on technet.
As well as changing your -or operators to -and as I mentioned, I put all conditions into the filter ending up with this:
Get-ADComputer -filter {
Enabled -eq $True -and
OperatingSystem -like '*2003*' -and
Name -notlike 'PING*' -and
Name -notlike 'PICT*' -and
Name -notlike 'PIRE*'
} | Select Name
I'm trying to filter out some junk on a simple where-object of services but the -notlike is going to get long, I've tried but can't get it working but is there a way to remove the duplicate -notlike into one for example -notlike 'Softw*','Applic*','this*','that*'
Where-Object { $_.StartMode -eq 'Auto' -and $_.State -ne 'Running' -and $_.Displayname -notlike '*.NET*' -and $_.Displayname -notlike 'Softw*'-and $_.Displayname -notlike 'Applic*'}
You could use -notmatch:
$_.Displayname -notmatch "(\.NET|Softw|Applic)"