views:

1011

answers:

2

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...

+1  A: 

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.

Andy Schneider
Thank you for the info. Considerig this is my 2nd attempt at making a powershell script I think I have gotten to a good start. Don Jones does show a nice way on outputting those values. I will look into that way for the future but for now will leave the script as is. It works and takes about 30 minutes to insert about 400 people into 400 different groups
Mitchell Skurnik
A: 

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
Mitchell Skurnik
I have not had a chance to get the portion of my script to check if the user is already in that group in sharepoint and if he should not be then delete him from it. I just finished this Yesterday at 9:00 ish
Mitchell Skurnik
FYI I am using portions of code from the following sites:http://www.codeplex.com/SharePointPSScripts/andhttp://www.powershell.nu
Mitchell Skurnik
I hope that you find this useful as the closest thing I could find to doing this was $800 from bamboo solutions. All in all it took about 24 hours to complete and as I said before this is my first real powershell script
Mitchell Skurnik