Mitchell Skurnik
Mitchell Skurnik

Reputation: 1489

Active Directory Filter memberof

I am trying to get all of the CN's out of active directory in order to populate groups based on that name into Sharepoint Services. I can list the "memberof" section but I can not seem to split it using split(",")

$Dom = 'LDAP://OU=External,OU=Users,OU=HomeOffice,DC=mydoman,DC=com'
$Root = New-Object DirectoryServices.DirectoryEntry $Dom 
$i=0
# Create a selector and start searching from the Root of AD
$selector = New-Object DirectoryServices.DirectorySearcher
$selector.SearchRoot = $root 
$adobj= $selector.findall() |`
where {$_.properties.objectcategory -match "CN=Person"} 
foreach ($person in $adobj){ 
    $prop=$person.properties
    $i++
    Write-host "$($prop.department) - $($prop.sn), $($prop.givenname)"
    Write-host $person.properties["memberof"]
}
"Total $i"

Now I get everything I need, but I need some way to filter only the CN's out...

Upvotes: 0

Views: 2801

Answers (2)

Mitchell Skurnik
Mitchell Skurnik

Reputation: 1489

test1.ps1

#Connet using LDAP
$Dom = 'LDAP://OU=External Accounts,OU=Users,OU=The Office,DC=mydomain,DC=com'
$Root = New-Object DirectoryServices.DirectoryEntry $Dom 

#Integer for the loop
$i=0

# Create a selector and start searching from the Root of AD
$selector = New-Object DirectoryServices.DirectorySearcher
$selector.SearchRoot = $root 

#Find the Groups
$adobj= $selector.findall() |`
where {$_.properties.objectcategory -match "CN=Person"} 
foreach ($person in $adobj){ 
    $prop=$person.properties
    $i++
    #Write-host "$($prop.department) - $($prop.sn), $($prop.givenname)" -foregroundcolor Magenta
    $test = $person.properties["memberof"]
    ForEach-Object {
        $test`
        -replace "CN=OLDLEGACYGROUP",""`
        -replace "CN=",""`
        -replace ",OU=Sales",""`
        -replace ",OU=Some Groups",""`
        -replace ",OU=Groups","" `
        -replace ",OU=The Office","" `
        -replace ",DC=mydomain","" `
        -replace ",DC=com","" `
        -replace ",","`r`n"
    }
}

test2.ps1

# Lets start with a clean slate :)
Clear

# Lets reference the assembly / GAC that we need for this
#region
[Void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")
$SPSite = New-Object Microsoft.SharePoint.SPSite("https://myintranetorextranetsite.myfqdn.com")
$OpenWeb = $SpSite.OpenWeb("/") 
#endregion

# Add some eye candy :)
# region
# I really wanted some old school thing in here :)
write-host "    _    ____       ____                   " -foregroundcolor Magenta
write-host "   / \  |  _ \     / ___| _   _ _ __   ___ " -foregroundcolor Magenta
write-host "  / _ \ | | | |____\___ \| | | | '_ \ / __|" -foregroundcolor Magenta
write-host " / ___ \| |_| |_____|__) | |_| | | | | (__ " -foregroundcolor Magenta
write-host "|_/   \_\____/     |____/ \__, |_| |_|\___|" -foregroundcolor Magenta
write-host "                          |___/            " -foregroundcolor Magenta
Write-Host "    Version 2.0" -foregroundcolor Red
Write-Host "    Build 2009 09-11 21:30" -foregroundcolor Red
Write-host "    Created by Mitchell J. Skurnik" -foregroundcolor Red
#endregion

# Create the stopwatch
#region
[System.Diagnostics.Stopwatch] $sw;
$sw = New-Object System.Diagnostics.StopWatch
$sw.Stop()
$sw.Start()
#endregion

# Function to control Adding groups
function creategroup
{
    param ([string] $siteurl = "https://myintranetorextranetsite.myfqdn.com")
    $site = New-Object Microsoft.SharePoint.SPSite($siteurl)
    $web = $site.RootWeb;
    $group = $currentgroup;
    $perm = "Read";
    $owner = "jdoe";
    if ($owner -eq "") { $owner = $web.CurrentUser.LoginName }

    $exists = $web.SiteGroups | where { $_.Name -eq $group }
    if ($exists -eq $null)
    {
        # Create group
        $web.SiteGroups.Add($group, $web.EnsureUser($owner), $null, "");
        # Give permissions to the group
        $assign = New-Object Microsoft.SharePoint.SPRoleAssignment($web.SiteGroups[$group]);
        $assign.RoleDefinitionBindings.Add($web.RoleDefinitions[$perm])
        $web.RoleAssignments.Add($assign)
        Write-Host -ForegroundColor green "Creating sharepoint group - " $currentgroup;
    } 
    $site.Dispose();
}

# Function to add users to the specified group
function addUser
{
    # Open a connection to the sharepoint  site and then select the sub site you want
    $themail = $prop.mail
    $thedisplay = $prop.displayname

    # If there are accounts that dont have some info lets populate it
    if ($themail -eq "")
    {
        $themail = "[email protected]"
    }
    if ($thedisplay -eq "")
    {
        $thedisplay = "Account, Test"
    }
    if ($themail -eq $null)
    {
        $themail = "[email protected]"
    }
    if ($thedisplay -eq $null)
    {
        $thedisplay = "Account, Test"
    }
    $TheNewGroup = $OpenWeb.SiteGroups | Where-Object {$_.Name -match $currentGroup}
    $TheNewGroup.AddUser("NTAMR\" + $prop.samaccountname,$themail,$prop.displayname,"")
    #write-host "Added: " $thedisplay -foregroundcolor Red
}

# Function to remove people - be careful using this script :(
# Also not done
function removeUser
{
    #$TheNewGroup = $OpenWeb.SiteGroups | Where-Object {$_.Name -match $currentGroup}
    #$TheNewGroup.AddUser("NTAMR\" + $prop.samaccountname,$themail,$prop.displayname,"")
    #$TheNewGroup.Remove($LoginToDel)
}

# Now onto the real stuff
Write-host "Searching for Groups" -foregroundcolor Green

# Clear out the existing text file so we have a clean slate
$file = New-Item -type file "C:\location\to\my\folder\allGroups.txt" -Force

# Execute the Group Dump Script
C:\location\to\my\folder\test.ps1 | Out-File -filepath "C:\location\to\my\folder\allGroups.txt" -append

# Clean up the list by removing duplicates and sorting everything
$TextFile = $TextFile = "C:\Powershell\allGroups.txt" 
$NewTextFile = "C:\Powershell\allGroups - Sorted.txt"
GC $TextFile | Sort | GU > $NewTextFile

# Use LDAP to connect to Active Directory
#region
$Dom = 'LDAP://OU=External Accounts,OU=Users,OU=The Office,DC=mydomain,DC=com'
$Root = New-Object DirectoryServices.DirectoryEntry $Dom 
#endregion

# Create a selector and start searching from the Root of AD
#region
$selector = New-Object DirectoryServices.DirectorySearcher
$selector.SearchRoot = $root 
#endregion

# Integer to compare file length
$c=0

# Get the Group text file's length and write to scree and variable
$fileLength = [System.IO.File]::ReadAllText($NewTextFile).Split("`n").Count
Write-Host "Found " $fileLength "Groups in Active Directory" -foregroundcolor Magenta

# Integer for thumbing through 'memberOf' in active directory
$d = 0

# Integer for the amount of of users found
$f = 0

# Start a while loop where we read through the entire groups text file
while ($c -le $fileLength)
{
    # Increment the line number for the next pass through
    $c++

    # Grab the first line of text from the groups file (Really the 0th line) and then tell the user
    $currentGroup = (Get-Content $NewTextFile)[$c]

    # Create the group
    CreateGroup
    #Write-Host "Created Group: " $currentGroup -foregroundcolor Red

    #
    Write-host $c "/" $fileLength "`t" $currentGroup -foregroundcolor Red

    # Query Active directory and force some commands
    $adobj= $selector.findall() | where {$_.properties.objectcategory -match "CN=Person"} 
    foreach ($person in $adobj)
    { 
        # Variable for the different properties to reduce fatigue
        $prop=$person.properties

        # The Department
        $department = $prop.department

        # Sir Name
        $sn = $prop.sn

        # Given Name
        $gn = $prop.givenname

        $un = $prop.samaccountname

        # Assign the really long memberof to a variable
        $memberof = $person.properties["memberof"]

        # Length of memberof
        $memberofcount = $test.Count


        # Loop for each group the member is in
        while ($d -le $memberof.Count)
        {
            $blah = ForEach-Object{`
                $memberof[$d]`
                -replace "CN=OLDLEGACYGROUP",""`
                -replace "CN=",""`
                -replace ",OU=Sales",""`
                -replace ",OU=Some Groups",""`
                -replace ",OU=Groups","" `
                -replace ",OU=The Office","" `
                -replace ",DC=mydomain","" `
                -replace ",DC=com","" `
            }
            # Incriment the d
            $d++

            # Is that user in the group?
            if ($blah -eq $currentGroup)
            {
                # Hey look we found somebody in that group :)
                Write-host "`t`t`t" $un -foregroundcolor Magenta
                addUser
                $f++
            }
            #elseif ($blah -ne $currentGroup)
            #{
            #   removeUser
            #}

            else
            {
                # Oh noes...nobody is in that group...that is strange
            }
        }


        # Are we at the end of what the user has
        if ($d -ge $memberofs.Count)
        {
            # Looks like we are :)
            $d=0
        }
    }

    # Display amount of users found
    #Write-Host "`t`t`t" $f " user(s) found"
    $f = 0
}

# Stop Watch
$sw.Stop()

# Write the compact output to the screen
write-host "Updated in Time: ", $sw.Elapsed.ToString()


#This space is saved for future development

Upvotes: 0

Andy Schneider
Andy Schneider

Reputation: 8684

As a general rule, write-host is not the best way to generate output. Ideally, you want to emit objects out of your function and let PowerShell do the formatting for you. This is the more "pipeline friendly" way of doing things. In this case, if you had a function Get-GroupMembers you could pipe it to something like

Get-Person | ft CN

The trick is creating a new object and adding properties to it, or just emitting the DirectoryServices object you are pulling already. To create a new custom object you can do the following:

$obj = new-object psobject 
$obj | add-member -membertype noteproperty name $PropName -value $valueToStore

People can use your function and pipe it to format-table, format-list, select-object, group-object, sort-object and a variety of other things. Keith Hill's Effective PowerShell has a great chapter on Output that you might find helpful.

There is also an article by Don Jones on using objects instead of text that is quite good as well.

Upvotes: 1

Related Questions