Anarko_Bizounours
Anarko_Bizounours

Reputation: 501

Powershell checking if OU exist

I'm trying to check if an OU exist before creating it. My problem is that I have 2 mother OU "USER BY SITE" and "GROUP BY SITE", and I need to have the exact same OU in those 2, 1 for storing users, the other for storing groups.

So far I used this function :

function CheckOUExist
{
    param($OUToSeek)

    $LDAPPath = "LDAP://dc=Domain,dc=local"

    $seek = [System.DirectoryServices.DirectorySearcher]$LDAPPath
    $seek.Filter = “(&(name=$OUToSeek)(objectCategory=organizationalunit))”
    $Result = $seek.FindOne()

    return $Result
}

There is my problem, I always get the OU existing in "GROUP BY SITE" even if $LDAPPath = "OU=USERS BY SITE,DC=Domain,DC=local". Am I missing something there? Is there a way to for the [System.DirectoryServices.DirectorySearcher] to work only in the OU I gived in the $LDAPPath?

If you need more accurate detail, I'll gladly provide them.

Thank you in advance.

Upvotes: 11

Views: 45936

Answers (5)

VertigoRay
VertigoRay

Reputation: 6273

The following, as suggested by Shay, works great if you're working with clean data.

[string] $Path = 'OU=test,DC=domain,DC=com'
[adsi]::Exists("LDAP://$Path")

Thanks for this great starting point! However, if you're verifying potentially unclean data, you'll get thrown an error. Some examples of possible errors are:

  • If the something isn't formatted properly
    • (ERR: An invalid dn syntax has been specified)
  • If the domain doesn't exist
    • (ERR: The server is not operational)
  • If the domain won't communicate with you
    • (ERR: A referral was returned from the server)

All of these errors should be caught with [System.Management.Automation.RuntimeException] or you can just leave the catch statement blank to catch all.

Quick Example:

[string] $Path = 'OU=test,DC=domain,DC=com'
try {
    $ou_exists = [adsi]::Exists("LDAP://$Path")
} catch {
    # If invalid format, error is thrown.
    Throw("Supplied Path is invalid.`n$_")
}

if (-not $ou_exists) {
    Throw('Supplied Path does not exist.')
} else {
    Write-Debug "Path Exists:  $Path"
}

More details: http://go.vertigion.com/PowerShell-CheckingOUExists

Upvotes: 15

TheQrtKenny
TheQrtKenny

Reputation: 11

How about:

#Requires -Version 3.0

# Ensure the 'AD:' PSDrive is loaded.
if (-not (Get-PSDrive -Name 'AD' -ErrorAction Ignore)) {
    Import-Module ActiveDirectory -ErrorAction Stop
    if (-not (Get-PSDrive -Name 'AD' -ErrorAction Silent)) {
        Throw [System.Management.Automation.DriveNotFoundException] "$($Error[0]) You're likely using an older version of Windows ($([System.Environment]::OSVersion.Version)) where the 'AD:' PSDrive isn't supported."
    }
}

Now that the AD: PSDrive is loaded, we have a couple of options:

$ou = "OU=Test,DC=Contoso,DC=com"
$adpath = "AD:\$ou"

# Check if this OU Exist
Test-Path $adpath

# Throw Error if OU doesn't exist
Join-Path 'AD:' $ou -Resolve

More info on this topic: Playing with the AD: Drive for Fun and Profit

Upvotes: 1

Andreas S Moe
Andreas S Moe

Reputation: 1

Import-Module ActiveDirectory
Function CheckIfGroupExists{
    Param($Group)
    try{
        Get-ADGroup $Group
    }
    catch{
        New-ADGroup $Group -GroupScope Universal
    }
}

Will also work

Upvotes: -1

Shay Levy
Shay Levy

Reputation: 126762

Try the Exists method, you get back true/false respectively:

[adsi]::Exists("LDAP://OU=test,DC=domain,DC=com")

Upvotes: 17

Artomegus
Artomegus

Reputation: 601

The problem is the construction of the DirectorySearcher object. To properly set the search root, the DirectorySearcher needs to be constructed using a DirectoryEntry object ([ADSI] type accelerator), whereas you are using a string. When a string is used, the string is used as the LDAP filter and the search root is null, causing the searcher to use the root of the current domain. That is why it looks like it isn't searching the OU you want.

I think you will get the results you are looking for if you do something like the following:

$searchroot = [adsi]"LDAP://OU=USERS BY SITE,DC=Domain,DC=local"

$seek = New-Object System.DirectoryServices.DirectorySearcher($searchroot)
$seek.Filter = "(&(name=$OUToSeek)(objectCategory=organizationalunit))"
... etc ...

Notice that a DirectoryEntry is first constructed, which is then used to construct the DirectorySearcher.

Upvotes: 2

Related Questions