Getting computername and the Canonical and distinguished OU name from AD

I have a list of servers where I need to get the OU, I have put together a script that will do this.

Get-ADOrganizationalUnit 
    -Identity $(($adComputer = Get-ADComputer -Identity $env:COMPUTERNAME).DistinguishedName.SubString($adComputer.DistinguishedName.IndexOf("OU=")))

The issue here is that the OU name is hard to read and not easy on the eye, so I figured out that what i need is the CanonicalName. However here is the problem.

I have come up with the snippet below.

Get-ADOrganizationalUnit -Filter * -properties CanonicalName, DistinguishedName 
    | select-Object CanonicalName,DistinguishedName  

The problem with the above is that it gets everything in AD, I need to be able to filter by servername so that when I load up the server list in a file, I can use a foreach loop to get a report of the servername and the OU, I have tried to use the -Server filter to no avail, as I believe that is for the AD server.

During my research I found, PowerShell filter by OU. In my test environment, it has been running for hours with no results back.

The snippet below will return groups, I cannot get servername filter to work.

Get-ADOrganizationalUnit -Properties CanonicalName -Filter * 
    | Sort-Object CanonicalName 
    | ForEach-Object { [pscustomobject]@ {
        Name          = Split-Path $_.CanonicalName -Leaf
        CanonicalName = $_.CanonicalName
        UserCount     = @(Get-AdUser -Filter * -SearchBase $_.DistinguishedName -SearchScope OneLevel).Count
      }
     }

Solution 1:

This is how I would do it:

  1. First query all the computers from your list. Here I'm assuming the computer list is coming from a CSV and the computers are on a column named Computers.
  2. Get the computer's Organizational Unit by removing the Common Name from their DistinguishedName: (.... -split '(?=OU=)',2)[-1]
  3. Add the computers objects to a Hash Table where the Keys are the computer's OUs. This will let us query each OU only once.
  4. Loop over the Hash Table keys (OU's DistinguishedName) querying their CanonicalName.
  5. Create a new object for each computer with the desired properties.
  6. Export the result to a Csv.
# If it's a txt file instead:
# $computers = Get-Content path/to/computers.txt
$csv = Import-Csv path/to/csv.csv
$map = @{}

# If it's a txt file, instead:
# foreach($computer in $computers)
foreach($computer in $csv.Computers)
{
    try
    {
        $adComputer = Get-ADComputer $computer
        $ou = ($adComputer.DistinguishedName -split '(?=OU=)',2)[-1]
        if($val = $map[$ou]) {
            $map[$ou] = $val + $adComputer
            continue
        }
        $map[$ou] = , $adComputer
    }
    catch
    {
        Write-Warning $_.Exception.Message
    }
}

$result = foreach($ou in $map.Keys)
{
    $params = @{
        Identity = $ou
        Properties = 'canonicalName'
    }

    try
    {
        $canonical = Get-ADOrganizationalUnit @params
        foreach($computer in $map[$ou])
        {
            [pscustomobject]@{
                'Computer Name'        = $computer.Name
                'OU DistinguishedName' = $ou
                'OU CanonicalName'     = $canonical.CanonicalName
            }
        }
    }
    catch
    {
        Write-Warning $_.Exception.Message
    }
}

$result | Export-Csv .... -NoTypeInformation