1

Im creating a script to help organize some groups for my school district. Long story short we have these 'Everyone groups' that are supposed to include all teachers/staff that are located at specific buildings. This data is stored in the 'Department variable' in AD. We also have a hold OU for staff that is no longer at the district, but we keep their accounts for 30 days that I don't want included. The result I have that works right now is as follows

Get-ADUser -Filter * -Properties sAMAccountName, department | Where { ($_.distinguishedName -notlike '*OU=Deactivated April 20th Hold*') } | Where { ($_.department -eq 'CENTENNIAL ELEMENTARY') } | Select sAMAccountName | Export-Csv -LiteralPath C:\Results\Everyone_Groups\CN.csv -NoTypeInformation
Get-ADUser -Filter * -Properties sAMAccountName, department | Where { ($_.distinguishedName -notlike '*OU=Deactivated April 20th Hold*') } | Where { ($_.department -eq 'CENTRAL ELEMENTARY') } | Select sAMAccountName | Export-Csv -LiteralPath C:\Results\Everyone_Groups\CR.csv -NoTypeInformation

and so on, with the name of the department changing for every school.

The downside of this is that I have to run that command nearly 25 times to grab all of the users for the different departments that I need.

I want to integrate IF statements into this so I only have to pull users 1 time and then filter them from there, to add an additional hurtle to this, I don't want to just pull all users so that option is out. I've come up with the following to achieve this.

Get-ADUser -Filter * -Properties sAMAccountName, department | Where ($_.distinguishedName -notlike '*OU=Deactivated April 20th Hold*')
    If ($_.department -eq 'CENTENNIAL ELEMENTARY'){
        Select sAMAccountName | Export-Csv -LiteralPath C:\Results\Everyone_Groups\CN.csv -NoTypeInformation -Append
        }

And from here I would add additional IF statements for each additional department. The problem is that this command returns nothing to me. It doesn't error out or anything, it just never produces the .csv I'm asking for.

Any ideas on this?

NorwegiaMan
  • 97
  • 1
  • 9
  • Your query to AD could be improved a lot using the AD Filter, all these departments, do you have them in an array ? Also the `-notlike '*OU=Deactivated April 20th Hold*'` is this one specific OU or there are many like these ? – Santiago Squarzon Sep 07 '22 at 21:09
  • 1
    You say you don't want to pull all users, but `Get-ADUser -Filter *` quite literally pulls all users. You filter things out after that with your `Where` statement, but you *are* pulling all users to start with. – TheMadTechnician Sep 07 '22 at 22:35
  • I've read this about 3 times now and I'm still a bit confused. What are the expected results? And, as MadTech points out, you grab every user and filter them out. The reason your 2nd example isn't working is because your `Where-Object` cmdlet expects a *scriptblock* `{...}`, not `(..)`. Then, you're referencing `$_` as if it were in a `Foreach-Object` loop, which it's not. Same goes for the `Select-Object` cmdlet you have by itself. Are your intentions to export users that have those departments mentioned into their own csv that aren't a part of the *Hold* OU? – Abraham Zinala Sep 07 '22 at 22:43
  • Thank you all so much. I'm still fairly new at PowerShell, pretty obvious from all this now. To answer questions, @SantiagoSquarzon - This would be a specific OU i'm trying to avoid, only one of its kind and I do have the departments in an array. I use it later on to remove all users from these groups if they are assigned the wrong group. @TheMadTechnician - You're right, I just couldn't think of a better way to use the `-Filter`. @AbrahamZinala - The results that I get are going to be a different .csv for each school, and a combined .csv for all schools. – NorwegiaMan Sep 08 '22 at 13:36

3 Answers3

2

First off, pulling users once is simple, just pull the users and capture the output in a variable. Once you have that you can sort them out from there easily enough.

$Users = Get-ADUser -Filter * -Properties sAMAccountName, department | Where { ($_.distinguishedName -notlike '*OU=Deactivated April 20th Hold*') }

From there you could just run it through a switch like:

Switch($Users){
    {$_.Department.ToUpper() -eq 'CENTENNIAL ELEMENTARY'} {$_|Select samaccountname|Export-Csv C:\Results\Everyone_Groups\CN.csv -NoTypeInformation -Append}
    {$_.Department.ToUpper() -eq 'CENTRAL ELEMENTARY'} {$_|Select samaccountname|Export-Csv C:\Results\Everyone_Groups\CR.csv -NoTypeInformation -Append}
}
TheMadTechnician
  • 34,906
  • 3
  • 42
  • 56
  • This worked perfectly! It completely annihilated the time it takes to run the script! It was throwing a weird error when adding `.ToUpper()` for some reason, but removing that little bit was the fix. – NorwegiaMan Sep 08 '22 at 14:41
2

If you're looking to filter for users in 'CENTRAL ELEMENTARY', 'CENTENNIAL ELEMENTARY', while excluding users in '*OU=Deactivated April 20th Hold*', then I would loop through each department making a call to Get-ADuser for each one:

$departments = 'CENTRAL ELEMENTARY', 'CENTENNIAL ELEMENTARY'
$OU = 'DistinguishedName=OU Here' # must be the containers full path. 
foreach ($department in $departments)
{
    Get-ADUser -LDAPFilter "(&(!($OU))(department=$department))" -Properties 'Department' | Select-Object -Property 'SAMAccountName' |
        Export-Csv -Path "C:\Results\Everyone_Groups\$department.csv" -NoTypeInformation
}

Now you can export based on the department and can add more later if needed; just add the new departments to $departments array, and it should export to a csv accordingly with the name as the department.

Abraham Zinala
  • 4,267
  • 3
  • 9
  • 24
  • 1
    I would do the same as you're doing here except that, same as mentioned before, `cn=*OU=Deactivated April 20th Hold*` is not valid (also I think you meant `DistinguishedName=`). You can however all OUs not like: `$ous = Get-ADOrganizationalUnit -LDAPFilter "(!name=*Deactivated April 20th Hold*)"` and then use that array as `-SearchBase` – Santiago Squarzon Sep 07 '22 at 23:38
  • @SantiagoSquarzon, thank you. Seeing as it's just a single container, will leave it for the OP to pre-fill it. I was about to stand up a domain environment just to test all this. These Adderall pills got me thinking too much lol – Abraham Zinala Sep 07 '22 at 23:49
0

Here is how I would do it to allow one merged export and one export per Department. The idea is to only query the specific OUs and let the Active Directory Filter to handle the search of users which's Department is one of the one we're interested on.

$departments = 'CENTENNIAL ELEMENTARY', 'CENTRAL ELEMENTARY'

# this creates a filter that can be read as:
# "query all users where their `Department` attribute is this or this or that..."
$params = @{
    LDAPFilter = '(|'
    Properties = 'Department'
}
foreach($department in $departments) {
    $params['LDAPFilter'] += '(department={0})' -f $department
}
$params['LDAPFilter'] += ')'

# looking at the LDAPFitler created for this example, it would look like this:
#
# Name                Value
# ----                -----
# LDAPFilter          (|(department=CENTENNIAL ELEMENTARY)(department=CENTRAL ELEMENTARY))

# now we can query all OUs which's `Name` is NOT LIKE `Deactivated April 20th Hold`
# and loop over these OUs
$results = foreach($ou in Get-ADOrganizationalUnit -LDAPFilter "(name=*Deactivated April 20th Hold*)") {
    # set the `SearchBase` for filtering each OU
    $params['SearchBase'] = $ou.DistinguishedName
    # get the results for this OU
    Get-ADUser @params | Select-Object SamAccountName, Department
}

# export all merged data
$results | Export-Csv path\to\folder\mergeddata.csv -NoTypeInformation

# export one Csv per department, the Csv will have the department's name
$results | Group-Object Department | ForEach-Object {
    $path = Join-Path path\to\folder\ -ChildPath ($_.Name + '.csv')
    $_.Group | Export-Csv $path -NoTypeInformation
}
Santiago Squarzon
  • 41,465
  • 5
  • 14
  • 37