【问题标题】:Organizing Active Directory accounts组织 Active Directory 帐户
【发布时间】:2015-06-18 10:30:49
【问题描述】:

我正在尝试使用一个脚本来根据其显示名称组织我的 Active Directory 帐户,因为我们所有的帐户的名称中都有其 OU(或 subOU)。我正在尝试使用 PowerShell 中 ForEach 循环内的 If 语句来执行此操作。但是,每次我运行它时,它都会不断询问我的身份。谁能帮我解决这个问题?这就是我所拥有的......

Import-Module ActiveDirectory
$OU = "OU=Test, OU=com"
$Test1OU = "OU=Test1, OU=Test, OU=Com"
$Test2OU = "OU=Test2, OU=Test, OU=Com"

$Users = (Get-ADUser -SearchBase $OU -Filter * -Properties samAccountName,DisplayName)
ForEach ($user in $users)
{
If ($($user.DisplayName -like ("*Supply*" -or "*Supplies*"))
{Move-ADObject -Identity $($user.samAccountName -TargetPath $Test1OU}
ElseIf ($($user.DisplayName -like ("*Accounting*" -or "*Accountant*"))
{Move-AdObject -TargetPath $Test2OU}
}

【问题讨论】:

  • Move-ADObject 什么?您指定了目的地,但没有指定要移动的对象。
  • 仍然是 PowerShell tbh 的新手,但我认为要移动的对象是 if 语句中具有显示名称的对象,例如“supply”等...
  • 无论如何您都必须将对象提供给 cmdlet,并且它应该是 AD 对象,而不是选择结果。您应该使用Get-ADUser 原始输出来操作它们,而不是使用select 并使用字符串。如果您这样做foreach ($user in $users) { $_.displayname},您仍然可以从用户列表中获取字符串
  • 所以我将 if 语句更改为... If($_.DisplayName -like ("Supply" -or "Supplies") ) 和 ForEach 到 ($User in $Users) 并且命令运行但没有执行任何操作...至少我遇到了一个问题...我也确保使用 Get-ADUser ,你还看到什么我做错了吗?
  • 不要组合 -like 检查,-like 期望在其右侧有一个字符串,而不是带有 -or 的表达式,这使其成为布尔值。此外,使用-match 可以让您在要匹配的任一字符串中删除包装星号。 if ($_.DisplayName -match "Supply" -or $_.displayname -match "Supplies") ...

标签: powershell active-directory organization ou


【解决方案1】:

你在这里遇到了一些问题

  1. 就像 Vesper 说你没有将任何东西传递给 Move-ADObject 因此你得到的错误
  2. $DisplayNames 不是名称的字符串数组,而是具有 displayname 属性的对象。这就是-ExpandProperty 参数的用途,Select-Object 仅供参考。
  3. 您正在拉动所有用户,但实际上只想处理某些用户。而不是-Filter *,让我们使用更有针对性的方法。
  4. 虽然它很诱人,但你不能嵌套-like 这样的条件。如果您使用"*Supply*" -or "*Supplies*" 并键入它将评估为真。与所有非零长度字符串相同。

对于我们计划做的事情,我们不必解决所有这些问题。我们应该使用管道来帮助解决这个问题。根据有多少差异,您有类似 switch 语句的东西可能会更好,这将在下面介绍。

$supplyFilter = 'DisplayName -like "*Supply*" -or DisplayName -like "*Supplies*"'
$accountFilter = 'DisplayName -like "*Accounting*" -or DisplayName -like "*Accountant*"'

Get-ADUser -SearchBase $OU -Filter $supplyFilter -Properties displayName | Move-ADObject -TargetPath $Test1OU
Get-ADUser -SearchBase $OU -Filter $accountFilter -Properties displayName | Move-ADObject -TargetPath $Test2OU

您可能会对此感到奇怪,并使用过滤器和目标对在循环中创建一个自定义对象,这样您就不需要对每个 Get-ADuser 实例重复 cmdlet 调用。

$moves = @(
    @{
        Filter = 'DisplayName -like "*Supply*" -or DisplayName -like "*Supplies*"'
        OU = "OU=Test1, OU=Test, OU=Com"  
    },
    @{
        Filter = 'DisplayName -like "*Accounting*" -or DisplayName -like "*Accountant*"'
        OU = "OU=Test2, OU=Test, OU=Com"
    }
) | ForEach-Object{New-Object -TypeName PSCustomObject -Property $_}

ForEach($move in $moves){
    Get-ADUser -SearchBase $OU -Filter $move.Filter -Properties displayName | Move-ADObject -TargetPath $move.OU
}

您应该能够通过添加新的$moves 轻松扩展至此。使用 PowerShell v3.0 会更干净,但我不知道你有什么版本。

使用开关

如果你想要更接近你目前拥有的东西,我会建议这样的东西。

$Users = Get-ADUser -SearchBase $OU -Filter * -Properties DisplayName
ForEach ($user in $users){
    switch($user.DisplayName)  {
        ($_ -like "*Supply*" -or $_ -like "*Supplies*"){Move-ADObject -Identity $user -TargetPath $Test1OU}
        ($_ -like "*Accounting*" -or $_ -like "*Accountant*"){Move-ADObject -Identity $user -TargetPath $Test1OU}
    }
}

【讨论】:

  • 这是我一开始就应该做的,因为它更多的是在我的联盟中。然而,我试图让一些东西更像我的东西,主要是为了获得使用 ForEach 和 If's 的经验,并在网络上运行一些不太密集的东西。更不用说,我想要我办公室里的人可以点击并运行而不会弄乱我的脚本的东西。感谢您的帮助,我正在研究这个,将来很可能会坚持使用这些类型!
  • @WeeWoo 我不明白关于在网络上不太密集的东西的评论。我的版本明显更有效率。你期待什么变化?你现在拥有的东西需要改变吗?你认为你的脚本目前会更容易向外扩展吗?
  • 该网络有超过 3000 名用户,分布在大约 5 个 OU 中。我的任务是在正确的 OU 中组织它们,然后将它们全部重命名......我只是认为在网络上为每个 OU 运行另一行可能很粗糙,因为它每次看起来都会搜索每个帐户过滤器。
  • 如果你不打算使用它,我会认为它更粗糙。运行多个有针对性的命令我认为它会减少负担然后将所有内容都拉回来。我没有用户群来对这种比较进行基准测试。 @WeeWoo 我提供了 3 个应该都可以工作的解决方案。看看有没有适合您的需求。
  • 看起来这个开关对我来说可能更容易使用,并且更接近我最初寻找的东西。我对 PowerShell 还是很陌生,所以请原谅我的无知。我不确定哪个会更好。我将不得不研究开关的工作原理。你给我看的数组实际上可能更好......我会去测试并告诉你。
【解决方案2】:

我目前无法测试,但这应该可以解决问题:

Import-Module ActiveDirectory

$OU = "OU=Test, OU=com"
$Test1OU = "OU=Test1, OU=Test, OU=Com"
$Test2OU = "OU=Test2, OU=Test, OU=Com"

$users = (Get-ADUser -SearchBase $OU -Filter * -Properties displayName)
foreach ($user in $users)
{
    if ($($user.displayName) -like "*Supply*" -OR $($user.displayName) -like "*Supplies*")){
        Move-ADObject -Identity $user -TargetPath $Test1OU
    }
    elseif ($($user.displayName) -like "*Accounting*" -OR $($user.displayName) -like "*Accountant*")) {
        Move-AdObject -Identity $user -TargetPath $Test2OU
    }
}

我已向 Move-ADObject 添加了一个标识参数,我还更改了一些 var 名称以更好地反映它们的内容。

【讨论】:

  • "*Supply*" -or "*Supplies*" 将始终评估为真。仔细检查 if 条件,然后我认为整个事情都是真的......不确定。
  • @Matt 是的,这将等于($($user.displayName) -like "True")。呵呵。
  • Move-ADObject 如果您已经将$user 作为要移动的对象,则不需要您提供samAccountName 值。所以最好把这个大结构换成Move-AdObject -Identity $user -targetpath ...
  • 是的,-or 是错误的,我现在已经修改,所以它们可以正常工作,正如@Vesper 建议的那样,我使用 $user 作为身份。
猜你喜欢
  • 1970-01-01
  • 2011-05-19
  • 1970-01-01
  • 1970-01-01
  • 2015-04-24
  • 1970-01-01
  • 2022-01-02
  • 2020-09-20
相关资源
最近更新 更多