如何将多个用户转移到多个OU,以从CSV导入用户并按部门进行过滤

时间:2019-09-16 00:44:08

标签: powershell

一般来说,PowerShell和脚本是新手。为了提高入职流程的自动化程度,我们必须每两个月将多个用户帐户移至多个OU。

Import-Module ActiveDirectory
$dept1 = "OU=Path1,DC=SOMEWHERE,DC=OUTTHERE"
$dept2 = "OU=Path2,DC=SOMEWHERE,DC=OUTTHERE"
Import-Csv "C:\Scripts\Incoming.csv" | ForEach-Object {
    $samAccountName = $_."samAccountName"
Get-ADUser -Identity $samAccountName -Filter {Department -eq "Dept1"} | Move-ADObject -TargetPath $dept1
Get-ADUser -Identity $samAccountName -Filter {Department -eq "Dept2"} | Move-ADObject -TargetPath $dept2
}

这实际上将所有带有部门标记的用户移动到我设置的路径中。但是我只希望它查看csv中的那些用户,然后从AD中过滤其部门-而不是CSV。我感觉好像错过了一步,但是我到处搜索并尝试获得帮助。我觉得我需要获取身份,然后针对其他内容进行搜索/过滤,但我不太确定该如何做。不胜感激。

修改

好的,如果我运行以下命令:


Get-ADUser -Filter {Department -eq "Dept1"} -Properties Department

它将返回适合该属性的每个人,但是如何将它们与$ samAccountName进行比较,并且仅尝试移动这些帐户或针对列表中的帐户运行命令?当我运行命令的后半部分时,它试图全部移动它们并失败了。


Move-ADObject $samAccountName -Target $dept1

我觉得很蠢

1 个答案:

答案 0 :(得分:2)

感觉很蠢。您不是,每个人在尝试学习新事物时都会有这种感觉。您也在这里寻求帮助,因此与其他许多人相比,您在比赛中处于领先地位。

@Lee_Daily的评论是正确的,因为Get-ADUser不支持在同一命令中同时使用-Identity-Filter。它们是不同的parameter sets的一部分。您可以从Get-Help Get-ADUseronline docs的语法输出中看出。两者都显示3组不同的参数,并且Identity和Filter不在同一组中。奇怪的是您的原始脚本应该抛出错误,因为您试图在同一命令中使用两者。不过现在不必担心。

这是人们完成这项任务的一种典型方式。首先,您查询用户的详细信息,包括您要决定的部门。然后,编写条件并执行适当的操作。这样做意味着您只需要为CSV中的每个用户查询一次AD,而不是像原始脚本那样查询两次,这有利于脚本性能和AD加载。 ForEach-Object循环的内部可能看起来像这样。 请注意,在Get-ADUser中添加了-Properties department。我们需要明确要求它,因为默认结果集中未返回部门。

# all of this goes inside your existing ForEach-Object loop

$u = Get-ADUser -Identity $_.samAccountName -Properties department

if ($u.Department -eq 'Dept1') {
    $u | Move-ADObject -TargetPath $dept1
} elseif ($u.Department -eq 'Dept2') {
    $u | Move-ADObject -TargetPath $dept2
}

现在让我们讨论一些解决此问题的替代方法。

第一种方式可以翻转内容,因此您最终只调用一次Get-ADUser,但是最终在客户端进行了很多过滤/处理。这不是我的最爱,但是它可以帮助您理解我的首选解决方案。具体来说,Get-ADUser调用使用-LDAPFilter参数。如果您从未见过LDAP filter syntax,这有点奇怪,这个特定示例可以轻松地使用更常见的-Filter语法。但是在下一个示例中,这将变得更加困难,并且学习LDAP过滤器语法使您能够从任何东西(而不仅仅是PowerShell)查询AD。

# instead of immediately looping on the CSV we imported, save it to a variable
$incoming = Import-Csv "C:\Scripts\Incoming.csv"

# then we make a single AD query for all users in either Dept1 or Dept2
$users = Get-ADUser -LDAPFilter '(|(department=Dept1)(department=Dept2))' -Properties department

# now we filter the set of users from AD by department and whether they're in the CSV and do the moves as appropriate
$users | Where-Object { $_.department -eq 'Dept1' -and
    $_.samAccountName -in $incoming.samAccountName } | Move-ADObject -TargetPath $dept1
$users | Where-Object { $_.department -eq 'Dept2' -and
    $_.samAccountName -in $incoming.samAccountName } | Move-ADObject -TargetPath $dept2

此方法的好处是用户可以进行一次AD往返,而不是CSV中的每个来回。但是,还有更多的本地循环会使用CSV中的samAccountNames检查结果中的samAccountNames,如果您的CSV和/或AD很大,则在cpu上可能会变得昂贵。

最后一个示例通过扩展LDAP过滤器并让AD进行更多工作来调整上一个示例。 荒谬擅长返回LDAP查询结果。经过数十年的微调,您可以做到这一点。因此,我们应该尽可能地利用它。

基本上,我们要做的是从CSV的samAccountNames中创建一个巨大的“ OR”过滤器,以便在获得结果时,唯一要做的检查就是部门检查。我在脑海中对这个查询进行口头表达的方式是,我们要求AD“返回所有用户,其中SamAccountName是A或B或C或D,等等,而Department是Dept1或Dept2。过滤器的一般形式如下所示(包含空格以提高可读性)

(& <SAM FILTER> <DEPT FILTER> )

# Where <DEPT FILTER> is copied from the previous example and
# <SAM FILTER> is similar but for each entry in the CSV like this
(|(samAccountName=a)(samAccountName=b)(samAccountName=c)...)

所以让我们看看它的作用。

# save our CSV to a variable like before
$incoming = Import-Csv "C:\Scripts\Incoming.csv"

# build the SAM FILTER
$samInner = $incoming.samAccountName -join ')(samAccountName='
$samFilter = "(|(samAccountName=$samInner))"

# build the DEPT FILTER
$deptFilter = '(|(department=Dept1)(department=Dept2))'

# combine the two with an LDAP "AND"
$ldapFilter = "(&$($samFilter)$($deptFilter))"

# now make our single AD query using the final filter
$users = Get-ADUser -LDAPFilter $ldapFilter -Properties department

# and finally filter and move the users based on department
$users | Where-Object { $_.department -eq 'Dept1' } | Move-ADObject -TargetPath $dept1
$users | Where-Object { $_.department -eq 'Dept2' } | Move-ADObject -TargetPath $dept2

有许多更有效的方法来构建LDAP过滤器字符串,但我想简化代码以提高可读性。与StackOverflow相比,使用更好的PowerShell语法突出显示还容易阅读得多。但是希望您能掌握要点。

使用此方法的唯一限制是当传入的CSV文件很大时。 LDAP过滤器可以有一个最大大小。尽管我不确定它是什么,但我个人从未真正达到约4000个过滤器用户的水平。但是,即使您必须将传入的CSV文件分成几千个用户的批次,它仍然可能比其他示例更有效。