【问题标题】:Active Directory Filter memberofActive Directory 筛选器成员
【发布时间】:2010-11-26 23:27:06
【问题描述】:

我正在尝试从活动目录中删除所有 CN,以便将基于该名称的组填充到 Sharepoint 服务中。我可以列出“memberof”部分,但我似乎无法使用 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"

现在我得到了我需要的一切,但我需要一些方法来只过滤掉 CN...

【问题讨论】:

  • 好的,所以使用它我可以过滤掉 cn 的 ForEach-Object {$test -replace "OU=BLAH","" -replace ",","rn"}但由于某种原因,我仍然得到了两次,我只能解析第一组 CN=Group1 CN=Group2 CN=Group3 CN=Group4 CN=Group1,OU=Groups,OU=Office,DC=mydomain,DC=com CN =Group2,OU=Groups,OU=Office,DC=mydomain,DC=com CN=Group3,OU=Groups,OU=Office,DC=mydomain,DC=com CN=Group4,OU=Groups,OU=Office,DC =mydomain,DC=com

标签: sharepoint powershell active-directory


【解决方案1】:

一般来说,write-host 不是生成输出的最佳方式。理想情况下,您希望从函数中发出对象并让 PowerShell 为您进行格式化。这是更“管道友好”的做事方式。在这种情况下,如果你有一个 Get-GroupMembers 函数,你可以通过管道将它传递给类似

Get-Person | ft CN

诀窍是创建一个新对象并向其添加属性,或者只是发出您已经提取的 DirectoryServices 对象。要创建新的自定义对象,您可以执行以下操作:

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

人们可以使用您的函数并将其通过管道传递给格式表、格式列表、选择对象、组对象、排序对象和其他各种东西。 Keith Hill 的 Effective PowerShell 有一个很棒的 chapter on Output,您可能会觉得很有帮助。

还有一篇Don Jones on using objects instead of text的文章也不错。

【讨论】:

  • 感谢您提供的信息。考虑一下,这是我第二次尝试制作 powershell 脚本,我认为我已经有了一个良好的开端。 Don Jones 确实展示了一种输出这些值的好方法。我将在未来研究这种方式,但现在将保持脚本不变。将大约 400 人插入 400 个不同的组中,大约需要 30 分钟
【解决方案2】:

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 = "testaccount@myfqdn.com"
    }
    if ($thedisplay -eq "")
    {
        $thedisplay = "Account, Test"
    }
    if ($themail -eq $null)
    {
        $themail = "testaccount@myfqdn.com"
    }
    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

【讨论】:

  • 我还没有机会获得我的脚本部分来检查用户是否已经在 sharepoint 中的该组中,如果他不应该从其中删除他。我昨天 9:00 才完成这个
  • 仅供参考,我正在使用来自以下站点的部分代码:codeplex.com/SharePointPSScriptspowershell.nu
  • 我希望你会发现这很有用,因为我能找到的最接近的东西是竹子解决方案的 800 美元。总而言之,完成大约需要 24 小时,正如我之前所说,这是我的第一个真正的 powershell 脚本
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-25
  • 1970-01-01
相关资源
最近更新 更多