【问题标题】:Powershell script to group multiple identical rows with different columnPowershell脚本将多个相同的行与不同的列分组
【发布时间】:2021-09-14 07:00:44
【问题描述】:

我有以下从 powershell 导出的 CSV "objectGUID","sAMAccountName","givenName","SN","Description","mail","memberOf","preferredLanguage","manager","title","company","distinguishedName"

唯一的区别是 MemberOf。 在 AD 中,用户是多个 AD 组的成员,我们要导出用户及其组,组必须在同一列中导出,而不是在不同的行中。

我为得到输出而编写的代码是

Import-Module ActiveDirectory
$Groups = import-csv CGroups.csv
Foreach ($Group in $Groups)
{

$Arrayofmembers = Get-ADGroupMember -identity $Group.identity | select name,samaccountname

foreach ($Member in $Arrayofmembers)
{
$user = Get-ADUser $member.samaccountname -properties mail,physicalDeliveryOfficeName,objectGuid,DisplayName,manager
$guid = $user.objectGuid
$immutableId = [System.Convert]::ToBase64String($guid.ToByteArray())
$OBJNEW=IID2GUID $immutableId
$objatt15 = $OBJNEW.att15
$ADObj = Get-ADUser -Filter "extensionattribute15 -eq '$objatt15'" -Server dc.contoso.com:3268 -SearchBase 'dc=contoso,dc=net' -Properties msRTCSIP-PrimaryUserAddress,extensionattribute8,mail,DisplayName,manager,title,company

$obj = New-Object -TypeName psobject
$obj | Add-Member -MemberType NoteProperty -Name objectGUID -Value $ADObj.objectGUID
$obj | Add-Member -MemberType NoteProperty -Name sAMAccountName -Value $ADObj.sAMAccountName
$obj | Add-Member -MemberType NoteProperty -Name givenName -Value $ADObj.givenName
$obj | Add-Member -MemberType NoteProperty -Name SN -Value $ADObj.Surname
$obj | Add-Member -MemberType NoteProperty -Name Description -Value $ADObj.Description
$obj | Add-Member -MemberType NoteProperty -Name mail -Value $ADObj.mail
$obj | Add-Member -MemberType NoteProperty -Name memberOf -Value $Group.identity
$obj | Add-Member -MemberType NoteProperty -Name preferredLanguage -Value $ADObj.preferredLanguage
$obj | Add-Member -MemberType NoteProperty -Name manager -Value $ADObj.manager
$obj | Add-Member -MemberType NoteProperty -Name title -Value $ADObj.title
$obj | Add-Member -MemberType NoteProperty -Name company -Value $ADObj.company
$obj | Add-Member -MemberType NoteProperty -Name distinguishedName -Value $ADObj.distinguishedName
$obj | export-csv -Append -NoTypeInformation CGroupExport.csv
}
}

【问题讨论】:

  • 您可以将用户所属的各个组与分隔符组合起来。这样,您可以从一个仅占据一列的数组创建一个字符串。在该属性上使用-join ';'
  • 你没有显示你的函数 IID2GUID,我也不明白为什么你会在循环中使用Get-ADUser 两次。你想要的输出到底是什么?
  • 好的,我刚刚注意到,所以最初的 Get-ADUser 来自源 AD,我们想在目标 AD 上进行匹配,我们使用 IID2GUID 来匹配 immutableid 但这不是这里的请求。目标是在字符串中获取该成员列。我的 powershell 编码技能仅限于您所看到的内容,因此,如果您可以建议 -join 的代码,那将非常棒。

标签: powershell group-by


【解决方案1】:

感谢您提供有关 IID2GUID 的信息,所以我不会打扰。

您的代码可以通过以下方式优化

  1. 捕获在变量中返回的对象并将其保存到 csv,而不是在每次迭代中附加到 csv
  2. 您似乎要求提供各种用户属性,这些用户属性从未使用过和/或默认情况下已由各种 Get-AD* cmdlet 返回
  3. 您正在构建每个“老派”对象,并使用 [PsCustomObject]@{..} 我认为代码的可读性会提高
Import-Module ActiveDirectory

$Groups = Import-Csv -Path 'X:\CGroups.csv'
# capture all output objects in a variable $result
$result = foreach ($Group in $Groups) {
    # Get-ADGroupMember can return objects of type group, user and computer
    # so we filter for users only. The objects returned already have an objectGUID property
    $Arrayofmembers = Get-ADGroupMember -Identity $Group.identity | Where-Object { $_.objectClass -eq 'user' }

    foreach ($Member in $Arrayofmembers) {
        $guid        = $Member.objectGUID
        $immutableId = [System.Convert]::ToBase64String($guid.ToByteArray())
        $OBJNEW      = IID2GUID $immutableId
        $objatt15    = $OBJNEW.att15

        # Get-ADUser by default returns these properties:
        # DistinguishedName, Enabled, GivenName, Name, ObjectClass, ObjectGUID, SamAccountName, SID, Surname, UserPrincipalName
        $adProps = 'Extensionattribute15','EmailAddress','DisplayName','Description','Manager','Title','Company','preferredLanguage'
        $ADObj   = Get-ADUser -Filter "extensionattribute15 -eq '$objatt15'" -Server 'dc.contoso.com:3268' -SearchBase 'dc=contoso,dc=net' -Properties $adProps
        if ($ADObj) {
            # output an object
            [PsCustomObject]@{
                objectGUID        = $ADObj.ObjectGUID
                sAMAccountName    = $ADObj.SamAccountName
                givenName         = $ADObj.GivenName
                SN                = $ADObj.Surname
                Description       = $ADObj.Description
                mail              = $ADObj.EmailAddress
                memberOf          = $Group.identity  # this will be grouped later
                preferredLanguage = $ADObj.preferredLanguage
                manager           = $ADObj.Manager
                title             = $ADObj.Title
                company           = $ADObj.Company
                distinguishedName = $ADObj.DistinguishedName
            }
        }
    }
}

# Now group the objects collected in $result on the `distinguishedName`
# property so we can combine the groups this user belongs to
$combined = $result | Group-Object distinguishedName | ForEach-Object {
    # output a new object for the user with the memberOf property combined
    $userGroups = $_.Group.memberOf -join '; '
    $_.Group[0] | Select-Object *, @{Name = 'memberOf'; Expression = {$userGroups}} -ExcludeProperty memberOf
}

# output the combined results in a CSV file
$combined | Export-Csv -Path 'X:\CGroupExport.csv' -NoTypeInformation

Manager 属性是该经理用户的 DistinguishedName。如果您想要名称,则可以将该属性更改为manager = (Get-ADUser -Identity $ADObj.Manager).Name

【讨论】:

  • 你好西奥。非常感谢您提供了非常改进的脚本。这里有一个问题。似乎 Get-AdPrincipalGroupMembership 不起作用。我收到此错误“Get-ADPrincipalGroupMembership:全局目录端口不支持该操作。”
  • @Cristi 我一直在谷歌上搜索这个错误,似乎Get-AdPrincipalGroupMembership 确实有问题...Microsoft 建议 “如果你想在另一个域中搜索本地组,使用 ResourceContextServer 参数来指定另一个域中的备用服务器。” 但即便如此,很多人说这对他们不起作用..
  • @Cristi 如果您对在输出的memberOf 属性中获得一组DN 感到满意,您可以将MemberOf 添加到$adProps 数组并设置$userGroups = $ADObj.MemberOf -join '; '。如果您不需要 DN,而是需要组名称,则需要遍历所有返回的组并执行 $userGroups = ($ADObj.MemberOf | ForEach-Object {(Get-ADGroup -Identity $_).Name} ) -join '; '。 (非常耗时..)
  • 你好西奥。我已经查看了您的建议,它似乎返回了用户所属的所有组,而不是仅列出我在初始列表中拥有的组。我的兴趣是查看用户是否只是我在 CSV 文件中提供的 $groups 中的那些组的成员
  • @Cristi 哦,我的错。我完全误读了它似乎..我现在已经更新了我的答案以在之后合并memberOf 属性
猜你喜欢
  • 2015-09-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多