List all OU with Users - powershell

I'm searching a way in PowerShell to list all OU with Users in it.
I tried something with Get-ADUser or Get-ADOrganizationalUnit but it doesn't really work.

One approach would be to get all of the OU's and check to see if they contain any users via -SearchBase. Filter them out with a Where-Object clause
Get-ADOrganizationalUnit -Filter * |
Where-Object {(Get-ADUser -SearchBase $_.DistinguishedName -Filter *).Count -gt 0} |
Select-Object -ExpandProperty DistinguishedName

Simply pull the OU from each user object. Then find unique values.
Get-ADUser -Filter * |
ForEach-Object {$_.DistinguishedName -replace '(^.*?)(OU=.*)','$2'} |
Sort-Object -Unique
Note: this makes the assumption that you are not storing user objects in Containers rather than OUs

Related

Powershell change multiple users AD properties

Still learning Powershell for AD and i have one question that is bothering me. Have to change AD properties for multiple users in AD within specific location, for example we have in same OU people from Berlin and from Washington, and cities are set in each profile, but im wondering if i need to get also properties before changing address for one of those locations like this
Get-ADUser -filter 'City -like "Berlin"' -SearchBase 'OU=Users,OU=Staff,DC=Contoso,DC=com' -Properties StreetAddress, PostalCode | % {Set-ADUser $_ -Replace #{StreetAddress="New street 11";PostalCode="221202XX"}}
or if it would work also without doing -Properties and just pipe filter City results to Set-ADUser
Thank you.
You do not need to specify -Properties unless you want to see them in the output. You also don't need the foreach, simply piping to Set-ADUser is sufficient.
Get-ADUser -filter 'City -like "Berlin"' -SearchBase 'OU=Users,OU=Staff,DC=Contoso,DC=com' |
Set-ADUser $_ -Replace #{StreetAddress="New street 11";PostalCode="221202XX"}
This will update those values just fine. The same is true for filtering. The following command will filter on the postalcode but it will not be included in the output unless you add -Properties postalcode
Get-ADUser -Filter "PostalCode -eq '221202XX'"
Thank you for answer, i have left out -Properties and that seems fine, also tried but this won't work without foreach as i guess Set-ADUser does not know which of those users that are filtered out needs to be updated. So i had to use
Get-ADUser -filter 'City -like "Berlin"' -SearchBase 'OU=Users,OU=Staff,DC=Contoso,DC=com' | % {Set-ADUser $_ -Replace #{StreetAddress="New street 11";PostalCode="221202XX"}}
while if i use without foreach
Get-ADUser -filter 'City -like "Berlin"' -SearchBase 'OU=Users,OU=Staff,DC=Contoso,DC=com' | Set-ADUser $_ -Replace #{StreetAddress="New street 11";PostalCode="221202XX"}
i get error
Set-ADUser : Cannot validate argument on parameter 'Identity'. The argument is null. Provide a valid value for the
argument, and then try running the command again.
but anyway, seems to be OK without -Properties which was my main concern

Combining PowerShell Commands

I've written two scripts that give me the independent output that I need, but am not sure how to put them together to give me the combined output.
Returns the count of all of the active users in a particular OU
(Get-ADUser -searchbase "OU=OU, DC=domain, DC=com" -filter * |Where {$_.enabled -eq "True"}).count
Returns the OU's underneath the same above OU that have "string" in the description property.
Get-ADOrganizationalUnit -searchbase "OU=OU, DC=domain, DC=com" -filter * -Properties description | where {$_.description -eq "string"}
What I'm trying to accomplish is for the script to give me a count of all of the active users underneath the OU's that have "string" in the description property.
I think this is the easiest way to achieve your goal
$OUs = Get-ADOrganizationalUnit -searchbase "OU=OU, DC=domain, DC=com" -filter * -Properties description | where {$_.description -eq "string"}
ForEach ($OU in $OUs) {
$count = (Get-ADUser -searchbase $OU -filter * | Where {$_.enabled -eq "True"}).count
Write-Host "OU $OU has $count users"
}
the result will be
OU OU=foo,DC=domain,DC=com has 6 users
OU OU=Computers,OU=foo,DC=domain,DC=com has 0 users
OU OU=Users,OU=foo,DC=domain,DC=com has 6 users
OU OU=Groups,OU=foo,DC=domain,DC=com has 0 users
Sergio Tanaka's helpful answer works well; let me complement it with a performance improvement:
You can greatly speed up your command by filtering at the source, by passing the filter criterion as a -Filter argument instead of retrieving all objects first and then filtering them with a separate Where-Object call:
Get-ADOrganizationalUnit -SearchBase 'OU=OU, DC=domain, DC=com' `
-Filter 'Description -eq "string"' -Properties description | #`
ForEach-Object {
$count = (Get-ADUser -SearchBase $_ -Filter 'Enabled -eq $true').Count
}
Note that the -Filter-string syntax of the AD cmdlets resembles PowerShell code, but it differs in many important ways - see Get-Help about_ActiveDirectory_Filter
The general advantages of using -Filter:
On a general note, the same performance improvement can be had with cmdlets for other PowerShell data providers, such as the one for the filesystem (e.g., Get-ChildItem), if they support a -Filter parameter:
A -Filter string is applied at the data source, which means that PowerShell only receives the result of the filtering.
Since providers are are implemented in compiled code (and they have access to lower-level internals), this generally makes for much better performance; additionally, in remoting scenarios performance improves by simply having to transfer less data over the network.
Note that -Filter parameters are always strings with provider-specific syntax, so you must consult the relevant provider/cmdlet documentation.

get-adgroup -filter "SID -like '*-512'"

I have been wanting to figure out how to use -filter to get what I want. What I am trying to do is find the Domain Admins group by a -like statement of *-512 against the SID property using the following:
get-adgroup -filter "SID -like '*-512'"
It works if I put the actual SID
get-adgroup -filter "SID -eq 'S-1-5-21domain-512'"
I know doing it this way will work
get-adgroup -filter * | ? {$_.SID -like '*-512'}
https://support.microsoft.com/en-us/help/243330/well-known-security-identifiers-in-windows-operating-systems
As BenH comments, you cannot partially filter on SIDs in LDAP queries, because of the way SID values are stored in the directory. The SID string you see is an SDDL representation of an underlying byte array.
I assume your motivation for attempting wildcard matching against a well-known RID is that you don't know the domain SID in advance. You can easily obtain that with the Get-ADDomain cmdlet:
$DomainSID = (Get-ADDomain).DomainSID
$DomainAdminsSid = New-Object System.Security.Principal.SecurityIdentifier ([System.Security.Principal.WellKnownSidType]::AccountDomainAdminsSid,$DomainSID)
Get-ADGroup -Filter {SID -eq $DomainAdminsSid}

How can I compare CSV to AD users and disable users not in CSV?

As a process to disable users, I have a CSV where users are identified by employeeID and not username. I need to loop through and compare the CSV to AD users, and any AD user not in the CSV needs to be disabled. This is what I have so far, but it's not working. I'll admit I'm still fairly new to powershell scripting, so any help would be much appreciated.
Import-Module ActiveDirectory
Import-Csv -Path c:\ADTerm.csv | foreach {Get-ADUser -filter * -SearchBase "ou=Test,ou=Logins,dc=domain,dc=com" -Identity $_.employeeID} | Where {$_ -ne $null} | Disable-ADAccount -Identity $_.employeeID
I cant really fit this all in a comment without it looking horrible so lets start with this.
You are combining -Filter and -Identity which most likely wont net the results you are looking for. Use Identity to get one specific user or filter to get one to many. Looking at TechNet for Get-AdUser you will see Identity only matches values to:
DistinguishedName
objectGUID
objectSid
sAMAccountName
In that regard I see you have a column for EmployeeID. I'm guessing that those are not SamAccountName which is one of the values that -Identity supports. I feel that you could do with the following changes.
$IDs = Import-Csv -Path c:\ADTerm.csv | Select-object -ExpandProperty EmployeeID
Get-ADUser -filter * -SearchBase "ou=Test,ou=Logins,dc=domain,dc=com" -Properties EmployeeID |
Where-Object{$_.EmployeeID -and ($IDs -notcontains $_.EmployeeID)} | Disable-ADAccount
Update the get-aduser to get all users in that OU. Get-Aduser does not return the EmployeeID by default so we use -Properties to specify it. Filter all those users that have employeeID but not one in the list. Disable-ADAccount will take the output of Get-AdUser nicely so there is not need to specify the account again.
Depending you might be storing this value as EmployeeNumber in AD. This is also dependent on your having a csv file with a column for EmployeeNumber

Get-ADComputer and MemberOf

I am very new to Powershell and am having an issue when using the Get-ADUser and GetADComputer cmdlets.
I am trying to use the Get-ADComputer and Get-ADUser to retrieve the memberOf from Active-Directory of all the users and computers. It only appears to be retrieving information from users and computers that are in 2 or more groups. Any users/computers that are only in 1 group display nothing.
For example: If UserA is in group Administrators I get no output when I use MemberOf. But if User2 is in both Administrators and Domains Administrators I get some output. However it will only output one of those groups.
Get-ADGroup does the same thing.
Is this normal? I can't imagine it is.
Here is my code:
Get-ADUser -Filter * -Properties * | Select-Object -Property Name,MemberOf | Sort-Object -Property Name
Thanks
Your trouble comes from the fact that the primary group is not part of the memberOf attribute.
So try this :
Get-ADUser -Filter * -Properties * | Select-Object -Property Name,MemberOf,PrimaryGroup | Sort-Object -Property Name
You'll find a deeper explanation in this answer.