How to correct an AD script in power shell - powershell

I make this script. This script counts how many users have each OU into the two Principal OU's ( RDS Funcional and VDI Funcional). The script works fine but i need to remove the total count of this two principals OU's. In the Image wants to remove the line RDS Funcional,"723". There an other line with this VDI Funcional,"295"
I need to remove both lines
Also remove the double quotes
Exemple in the image This line is fine -> 4127 Transportes Corporativos,16
Thanks :)
$log = #()
"OU=RDS Funcional,DC=esofitec,DC=loc","OU=VDI Funcional,DC=esofitec,DC=loc" | ForEach-Object {
Get-ADOrganizationalUnit -Filter * -SearchBase $_ | ForEach-Object {
$log += "Processsing {0}" -f $_.distinguishedname
[array] $users = Get-ADUser -Filter "Name -notlike 'test*' -and Name -notlike 'adm*'" -SearchBase $_.distinguishedname
if ($users -ne $null) {
$log += "{0} has {1}" -f $users.name, $users.count
[PSCustomObject]#{
OU = $_.name
Users = "{0}" -f $users.count
}
}
}
} | Export-Csv -Path c:\\ExportUsers.csv -NoTypeInformation -Delimiter ','
$log
Example in that Image:
Example

if you do not want the content of selected OU, but only 1st level children OU :
Get-ADOrganizationalUnit -SearchScope OneLevel -Filter * -SearchBase $_

Related

Get-ADUser - Filter child OU's and users where surname is empty then add to mail-enabled security group

I posted 4 days ago and the community have been really helpful! I can now look for users in a specific parent OU who have a last name.
My second step that I am trying to do is to now add those users who have a last name and are in the parent OU to a mail enabled security group. After some googling I found a piece of script that allows users to be added to such, but I need to edit to to specify my requirements. I thought I had tried to do this but it ended up still searching through the child OUs and adding those without a last name so I must have something wrong or jumbled.
My current script is
$Admin_Accounts = 'OU=Administrators,OU=Company,DC=CompanyDC,DC=local'
$Service_Accounts = 'OU=Administrators,OU=Company,DC=CompanyDC,DC=local'
$Disabled = 'OU=Administrators,OU=Company,DC=CompanyDC,DC=local'
$Test_PowerPoint_GPO = 'OU=Administrators,OU=Company,DC=CompanyDC,DC=local'
$Exclude = '({0}|{1}|{2})$' -f \[regex\]::Escape($Admin_Accounts), \[regex\]::Escape($Service_Accounts), \[regex\]::Escape($Disabled), \[regex\]::Escape($Test_PowerPoint_GPO)
Get-ADUser -Filter 'Enabled -eq $true' -SearchBase 'OU=Users,OU=Company,DC=CompanyDC,DC=local' |
Where-Object { !\[string\]::IsNullOrWhiteSpace($_.Surname) -and $_.DistinguishedName -notmatch $Exclude } |
Select-Object SamAccountName
$TargetGroup = “Company Team“
$TargetOU = “OU=Users,OU=Company,DC=Company,DC=local“
$Exclude = '({0}|{1}|{2})$' -f \[regex\]::Escape($Admin_Accounts), \[regex\]::Escape($Service_Accounts), \[regex\]::Escape($Disabled), \[regex\]::Escape($Test_PowerPoint_GPO)
$UserAccounts = Get-ADUser -Filter 'Enabled -eq $true' | ?{$_.DistinguishedName -like “_*$TargetOU*” -and $.Enabled -eq “True”}
Where-Object { !\[string\]::IsNullOrWhiteSpace($_.Surname) -and $_.DistinguishedName -notmatch $Exclude } |
Select-Object SamAccountName
ForEach($User in $UserAccounts)
{
$UsersName = $User.Name
\#Check for group membership
$Membership = Get-ADGroup $TargetGroup | Get-ADGroupMember | ?{$\_.Name -eq $UsersName}
if(!$Membership)
{
“Adding $UsersName to $TargetGroup”
Get-ADGroup $TargetGroup | Add-ADGroupMember -Members $User -Verbose
}
}
I tried to add pieces of script to specify my requirements
Seems to me your script is way more complex than it needs to be:
$Admin_Accounts = 'OU=Administrators,OU=Company,DC=CompanyDC,DC=local'
$Service_Accounts = 'OU=Administrators,OU=Company,DC=CompanyDC,DC=local'
$Disabled = 'OU=Administrators,OU=Company,DC=CompanyDC,DC=local'
$Test_PowerPoint_GPO = 'OU=Administrators,OU=Company,DC=CompanyDC,DC=local'
# Create regex matching list
[regex]$Exclude = "$Admin_Accounts|$Service_Accounts|$Disabled|$Test_PowerPoint_GPO"
$UserAccounts = Get-ADUser -Filter 'Enabled -eq $true' | Where-Object {
$_.DistinguishedName -like “_*$TargetOU*”
} | Where-Object {
![string]::IsNullOrWhiteSpace($_.Surname) -and $_.DistinguishedName -notmatch $Exclude
} | Select-Object SamAccountName

Get-ADUser - Filter child OU's and users where surname is empty

I am trying to run a command where I get all active directory users in the parent OU (Users) and filter out the child OU's (Admin accounts, service accounts, disabled accounts) as well as filter out any user account that does not have a surname in the surname field.
At the moment I have
Get-ADUser -Filter{enabled -eq $true} -SearchBase 'OU=Users,OU=Company,DC=CompanyName,DC=local' | Where-Object { $_.DistinguishedName -notlike "*,$Disabled" } | Where {$_.Surname -notlike "$Null"} | select samAccountName
When I add another child OU after 'Disabled' there is an error
Where-Object : A positional parameter cannot be found that accepts argument 'Where'.
Please may someone advise on how to filter out additional child OU's?
Good day Smoore
The problem is you are using multiple Where-object cmdlets but you only need one and separate them using () and adding the -and option, also to refer to $null value you don't need to use the "" marks
Get-ADUser -Filter {Enabled -eq $true} -SearchBase "OU=Users,OU=Company,DC=CompanyName,DC=local" | Where-Object {($_.DistinguishedName -notlike "*,$Disabled*") -and ($_.Surname -notlike $Null)} | select samAccountName
With this options you should be able to get all the users you want
Have a nice day!
I would use a regex -notmatch so it would be possible to combine all OU Distinguished names in just one variable.
Something like this:
$Admins = 'OU=Administrators,OU=Company,DC=CompanyName,DC=local'
$Service = 'OU=ServiceAccounts,OU=Company,DC=CompanyName,DC=local'
$Disabled = 'OU=DisabledUsers,OU=Company,DC=CompanyName,DC=local'
# build a regex string from the above OU DistinguishedNames
$Exclude = '({0}|{1}|{2})$' -f [regex]::Escape($Admins), [regex]::Escape($Service), [regex]::Escape($Disabled)
Get-ADUser -Filter 'Enabled -eq $true' -SearchBase 'OU=Users,OU=Company,DC=CompanyName,DC=local' |
Where-Object { ![string]::IsNullOrWhiteSpace($_.Surname) -and $_.DistinguishedName -notmatch $Exclude } |
Select-Object SamAccountName
As per your comment:
$Admins = 'OU=Administrators,OU=Company,DC=CompanyName,DC=local'
$Service = 'OU=ServiceAccounts,OU=Company,DC=CompanyName,DC=local'
$Disabled = 'OU=DisabledUsers,OU=Company,DC=CompanyName,DC=local'
# the group you want to add the users to
$TargetGroup = 'Company Team'
# build a regex string from the above OU DistinguishedNames
$Exclude = '({0}|{1}|{2})$' -f [regex]::Escape($Admins), [regex]::Escape($Service), [regex]::Escape($Disabled)
$users = Get-ADUser -Filter 'Enabled -eq $true' -SearchBase 'OU=Users,OU=Company,DC=CompanyName,DC=local' |
Where-Object { ![string]::IsNullOrWhiteSpace($_.Surname) -and $_.DistinguishedName -notmatch $Exclude }
# get the AD group as object
$GroupObject = Get-ADGroup -Filter "Name -eq '$TargetGroup'"
# now add these users that have Surnames to the security group all in one go
try {
Write-Host "Adding $(#($users).Count) users to group $TargetGroup"
$GroupObject | Add-ADGroupMember -Members $users -ErrorAction Stop -Verbose
}
catch {
Write-Warning "Error: $($_.Exception.Message)"
}
# or if you prefer loop through the users and add each one individually then use this instead
# foreach ($user in $users) {
# try {
# Write-Host "Adding user $($users.Name) to group $TargetGroup"
# $GroupObject | Add-ADGroupMember -Members $user -ErrorAction Stop -Verbose
# }
# catch {
# Write-Warning "Error adding user $($users.Name) to group $($TargetGroup): $($_.Exception.Message)"
# }
# }

Issue with powershell output ad-computer foreach

$computers = Get-ADComputer -Filter * -Properties * | Where-Object {$_.Name -like "LT*" -or $_.Name -like "PC*" -or $_.Name -like "MC*"} | Select name,lastlogondate
"You have [{0}] computers in domain [{1}]" -f $computers.count, (get-addomain).dnsroot
$today = Get-Date
$monthago = $today.AddDays(-30)
"Looking for systems that have not logged in since $monthago"
foreach ($computer in $computers)
{
if ($computer.lastlogondate -lt $monthago)
{"Computer [$computer] suspect"
"last logon $($computer.lastlogondate)"
""}
}
returns the following result:
Computer [#{name=lt020367; lastlogondate=10/23/2019 11:45:38}] suspect
last logon 10/23/2019 11:45:38
Can someone possibly tell me why my output is resulting in [#{ and how to resolve?
by get-adcomputer [...] | Select name,lastlogondate you are creating an object. To output properties of those objects, simply use:
"Computer [$($computer.name)] suspect"
"last logon $($computer.lastlogondate)"
By the way:
Getting all * properties is not ideal. Always filter as early as you can: -properties lastlogondate (name is always returned). Same goes for -filter "name -like 'LT*' -or name -like 'PC*' -or name -like 'MC*'".
Also be careful as lastlogondate of computer objects in AD is not synced between domain controllers.

Compare list of computer from text file with AD-User property

I new in Powershell world and trying to write a script which perform following:
Get List of Computers from a text file
Get list of Users from a text file
Control if the computer name is added in LogonWorkstations field in each user account
Here is the script I have written as of yet.
$Computers = Get-Content Computers.txt
$Users = Get-Content -Path Users.txt | Sort-Object -Unique
$ADUsers = Get-ADUser -Filter * -Properties LogonWorkstations -SearchScope Subtree -SearchBase "OU=ck,OU=users-com,DC=domain,DC=com" |
Where-Object {$Users -contains $_.Name} | Format-List Name,LogonWorkstations
As the script shows I read and retrieve property for Users and have list of computers in text file.
There are 50+ computers and users my question is how can I compare this line wise example check if computer from line 1 of Computers.txt exist in LogonWorkstations property of user from line 1 of Users.txt?
If each line of both files are corresponding, you can use a simple for loop to iterate through both lists simultaneously. $ADUsers will contain the output of ADUser objects matching the conditions.
$ADUsers = for ($i = 0; $i -lt $Users.Count; $i++) {
Get-ADUser -Filter "Name -eq '$($Users[$i])'" -Properties LogonWorkstations |
Where-Object { ($_.LogonWorkstations -split ',') -contains $Computers[$i] }
}
Since LogonWorkstations contains a comma-separated string, you will have to do some string manipulation. Using the -split operator on the , character will result in an array of strings. The -contains operator works nicely when comparing an item or collection of items to a single item.
If you want to compare the LogonWorkstations value of a user to any computer in the list, you can do something like the following:
$ADUsers = foreach ($User in $Users) {
Get-ADUser -Filter "Name -eq '$User'" -Properties LogonWorkstations | Where-Object {
Compare-Object -Ref ($_.LogonWorkstations -split ',') -Dif $Computers -IncludeEqual -ExcludeDifferent
}
}
Compare-Object here will only return a value if there is an exact match.
Note: I believe the LogonWorkstations attribute has been replaced with UserWorkstations attribute. Both may work now but may not be guaranteed in the future.
I haven't tried the below code but hopefully, you will be able to work out any little issues:
$computers = Get-Content -Path #PATHTOCOMPUTERS.TXT
$users = Get-Content -Path #PATHTOUSERS.TXT | Sort-Object -Unique
#Set a counter to zero
$counter = 0
foreach ($user in $users){
try{
#Get the current user from AD
$adUser = Get-ADUser -Filter { Name -eq $user} -Properties LogonWorkStations -ErrorAction Stop
#Uses the current index using $counter to get the correct computer from computers.txt and
#checks if the user has it setup as a LogonWorkStation
if ($adUser.LogonWorkstations -eq $computers[$counter]){
Write-Host "$user has $computer as a logon workstation"
}else{
Write-Host "$user doesn't have $computer as a logon workstation"
}
}catch{
Write-Host "Failed to get the AD user"
}
#Increment the $counter
$counter++
}

Get recursive group membership of all AD users using Powershell

I'm trying to make a PS script which would list all Active Directory user group membership (recursive).
I already have working script:
import-module activedirectory
$users = get-aduser -Filter {Name -Like "*"} -Searchbase "ou=Users, dc=Domain" | Where-Object { $_.Enabled -eq 'True' }
$targetFile = "D:\users.csv"
rm $targetFile
Add-Content $targetFile "User;Group"
foreach ($user in $users)
{
$groups = Get-ADPrincipalGroupMembership $user
foreach ($group in $groups)
{
$username = $user.samaccountname
$groupname = $group.name
$line = "$username;$groupname"
Add-Content $targetFile $line
}
}
But script doesn't list groups recursively, i.e., if group listed in the output file is part of another group.
Example:
Group1: User
Group2: Group3: User
Script shows only Group1 and 3 but not 2.
What should I add to the first script that it writes group membership recursively?
Sorry I am publishing an answer for a question from 3 years ago but if someone will see it, it can help.
Credit to:
How to get ALL AD user groups (recursively) with Powershell or other tools?
You can use the LDAP_MATCHING_RULE_IN_CHAIN:
Get-ADGroup -LDAPFilter "(member:1.2.840.113556.1.4.1941:=CN=User,CN=USers,DC=x)"
You can use it anywahere that you can use an LDAP filter.
Example:
$username = 'myUsername'
$dn = (Get-ADUser $username).DistinguishedName
Get-ADGroup -LDAPFilter ("(member:1.2.840.113556.1.4.1941:={0})" -f $dn) | select -expand Name | sort Name
Fix in your script:
import-module activedirectory
$users = get-aduser -Filter {Name -Like "*"} -Searchbase "ou=Users, dc=Domain" | Where-Object { $_.Enabled -eq 'True' }
$targetFile = "D:\users.csv"
rm $targetFile
Add-Content $targetFile "User;Group"
foreach ($user in $users)
{
$dn = $user.DistinguishedName
$groups = Get-ADGroup -LDAPFilter ("(member:1.2.840.113556.1.4.1941:={0})" -f $dn) | select -expand Name | sort Name
foreach ($group in $groups)
{
$username = $user.samaccountname
$groupname = $group.name
$line = "$username;$groupname"
Add-Content $targetFile $line
}
}
If you make it a function you can call it recursively. Check this out, I think you'll be pleased with the results:
Function Get-ADGroupsRecursive{
Param([String[]]$Groups)
Begin{
$Results = #()
}
Process{
ForEach($Group in $Groups){
$Results+=$Group
ForEach($Object in (Get-ADGroupMember $Group|?{$_.objectClass -eq "Group"})){
$Results += Get-ADGroupsRecursive $Object
}
}
}
End{
$Results | Select -Unique
}
}
Toss that at the top of your script, and then call it for each user. Something like:
import-module activedirectory
$users = get-aduser -Filter {Name -Like "*"} -Searchbase "ou=Users, dc=Domain" -Properties MemberOf | Where-Object { $_.Enabled -eq 'True' }
$targetFile = "D:\users.csv"
rm $targetFile
Add-Content $targetFile "User;Group"
foreach ($user in $users)
{
$Groups = $User.MemberOf
$Groups += $Groups | %{Get-ADGroupsRecursive $_}
$Groups | %{New-Object PSObject -Property #{User=$User;Group=$_}}|Export-CSV $targetfile -notype -append
}
Now, depending on the size of your AD structure that may take quite a while, but it will get you what you were looking for.
It is very easy. Just use ActiveRoles Management Shell for Active Directory. Cmdlet Get-QADMemberOf with parameter Indirect is the one you are looking for. Example:
Get-QADMemberOf john.smith -Indirect
The Quest object returned already include All Recursive groupes (and first level users) in properties $_.AllMembers
Add-PSSnapin Quest.ActiveRoles.ADManagement
$UsersFirstLevel = ($Members | Get-QADObject -Type Group -DontUseDefaultIncludedProperties | Get-QADGroupMember -DontUseDefaultIncludedProperties | ?{$_.type -eq 'user'})
$UsersSubGroup = ($Members | Get-QADObject -Type Group -DontUseDefaultIncludedProperties | Get-QADGroupMember -DontUseDefaultIncludedProperties | ?{$_.type -eq 'group'}).Allmembers | Get-QADObject -DontUseDefaultIncludedProperties | ?{$_.type -eq 'user'}
$RecursiveUsers = $UsersFirstLevel
$RecursiveUsers += $UsersSubGroup
$RecursiveUsers = $RecursiveUsers | Sort-Object -Unique
Newer versions of PowerShell (AD Module) do have -Recursive switch. So you can easily use Get-ADGroupMember.
Example: Get-ADGroupMember -Identity My_Group -Recursive