【问题标题】:Fixing try/catch, and output修复 try/catch 和输出
【发布时间】:2019-10-14 15:00:21
【问题描述】:

我正在将用户的 OU 添加到组中,并且想要捕获:

  1. 已添加用户
  2. 已在列表中的用户
  3. 将以上内容输出到文件中

下面的当前代码工作和输出:

用户名组名时间戳 -------- --------- --------- %用户名%%组名% 14/10/2019 15:50:49

但是,catch 不会捕获组中已经存在的用户并报告控制台上的输出。导出到 CSV 仅包含 OU 中的所有用户并显示它添加的时间。

我希望catch 输出在屏幕上触发,并在导出的 CSV 文件中显示用户是否已添加或在此运行中添加。

我正在使用的代码:

$groupName = 'SOMEGROUP'
$ou = 'OU=Users,DC=DC,DC=LOCAL'
$cred = Get-Credential -Credential bsg\myusername$

$results = Get-ADUser -Filter * -SearchBase $ou -Credential $cred | ForEach-Object {
    #Add the user to the group here
    $userName = $_.Name
    try {
        Add-ADGroupMember -Identity $groupName -Members $_.DistinguishedName -Credential $cred -ErrorAction Stop
    } catch {
        Write-Warning "User $userName is already a member of group $groupName"
    }

    # output a PsCustomObject that gets collected in the $results variable
    [PsCustomObject]@{
        'UserName'  = $userName
        'GroupName' = $groupName
        'TimeStamp' = Get-Date
    }
}

# output on console
$results | Format-Table -AutoSize

# Export to CSV file
$results | Export-Csv C:\PS\AddADGroupToUsers.csv -NoTypeInformation

Read-Host -Prompt "Press Enter to exit"

我不确定Add-ADGroupMember。重要的是那里的 DistingushedName 而不是 $userName

我希望输出显示无效的catch

我在两个语句中都使用了-Credential $cred,有没有更简单的方法可以让所有内容都以-Credential 作为会话而不是命令来运行?


回复已阅读并理解。 我运行了脚本。用户已经在组中,所以我希望他们都回来,因为“用户已经是组的成员......”。但它似乎出错了。

最新更新后的错误消息(该组已经有很多成员):

Add-ADGroupMember : Cannot validate argument on parameter 'Members'. The argument is null, empty, or an element of the
argument collection contains a null value. Supply a collection that does not contain any null values and then try the
command again.
At C:\PS\add to usersNEW2.ps1:28 char:57
+ ... oupMember -Identity $groupName -Members $_.DistinghuishedName -ErrorA ...
+                                             ~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidData: (:) [Add-ADGroupMember], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.ActiveDirectory.Management.Commands.AddADGrou
   pMember

输出 CSV 不正确,因为没有添加用户,他们已经在其中。所以结果是错误的:

UserName    GroupName   TimeStamp           Status
TheUser     GROUPSActual    16/10/2019 15:23    User added successfully

所以远离 Theo 的代码,我尝试了 Ivan 的建议,但这需要很长时间:

# I'll use the DistinghuishedName because this is always unique in the forest
$currentMembers = Get-ADGroupMember -Identity $groupName | Select-Object -ExpandProperty DistinghuishedName

$results = Get-ADUser -Filter * -SearchBase $ou -credential $cred | ForEach-Object {

    # test if the user is already a member by checking the array

If ((Get-ADGroupMember -Identity $groupname).distinguishedName -contains $_.distinguishedName) {
    Write-Warning "User $userName is already a member of group $groupName"
}
else { 
    Add-ADGroupMember -Identity $groupName -Members $_.DistinguishedName -Credential $cred -ErrorAction Stop
}
        # output a PsCustomObject that gets collected in the $results variable
        [PsCustomObject]@{
            'UserName'  = $_.Name
            'GroupName' = $groupName
            'TimeStamp' = Get-Date
            'Status'    = $status
    }
}

我认为它正在工作,但需要几分钟才能从 7 个结果中获得 3 个结果,而原始代码在几秒钟内就可以工作。 编辑:代码已完成,并已写入托管警告。我知道我可以调整状态部分以将错误添加到状态中。只是不应该花这么长时间!

时间戳相隔几秒钟,但现在:

TimeStamp
16/10/2019 16:12
16/10/2019 16:14
16/10/2019 16:15
16/10/2019 16:16
16/10/2019 16:17
16/10/2019 16:18
16/10/2019 16:19

【问题讨论】:

    标签: powershell active-directory


    【解决方案1】:

    catch 块仅在 ErrorAction 设置为 Stop 时发生错误时执行。当用户已经是组的成员时,Add-ADGroupMember 不会返回错误。

    我建议在 try 块中的脚本中使用某种逻辑。类似的东西:

    If ((Get-ADGroupMember -Identity $groupname).distinguishedName -contains $_.distinguishedName) {
        Write-Warning "User $userName is already a member of group $groupName"
    }
    else { 
        Add-ADGroupMember -Identity $groupName -Members $_.DistinguishedName -Credential $cred -ErrorAction Stop
    }
    

    您仍然可以使用catch 块来处理可能发生的任何错误。

    【讨论】:

    • 您可能希望强制将if 条件作为数组进行评估:@((Get-ADGroupMember -Identity $groupname).distinguishedName) 以处理组中只有一个成员的情况。
    • 您应该收到Add-AdGroupMember : The specified account name is already a member of the group 异常。您使用的是什么操作系统?
    • @Theo 在我的实验室环境中,我无法重现任何异常消息,但我可以多次运行该命令Add-ADGroupMember -Identity group01 -Members test01,没有错误显示或存储到$Error变量。
    • 正确,如果我多次运行代码,我的环境中不会收到异常消息
    • 我尝试使用上面的代码以及$currentMembers = Get-ADGroupMember -Identity $groupName | Select-Object -ExpandProperty DistinghuishedName 的原始命令。但是脚本需要很长时间,您的代码是否再次运行 get-adgroupmember 命令?原始代码(虽然它不报告已添加成员的失败)需要几秒钟。现在代码需要几分钟。它似乎正在工作,但在 7 个用户中,它已经 10 分钟,并且成功地只捕获了 2 个已经是会员但仍在运行
    【解决方案2】:

    虽然我以前从未见过Add-ADGroupMember NOT 抛出异常Add-AdGroupMember : The specified account name is already a member of the group,但Ivan MIrchev 报告说,在他的环境中尝试添加已经是小组成员。

    如果在某些环境中确实如此,那么相信该异常不再是一个好主意,我们需要采取额外的步骤,首先获取该组所有当前成员的列表。
    这个额外的步骤当然会导致更长的处理时间..

    # Get all user objects s that are currently member of the group and capture only 
    # the usable property like SamAccountName or DistinghuishedName to use for the -Members 
    # parameter of Add-ADGroupMember.
    # the -Members parameter takes either:
    #   the DistinghuishedName
    #   the ObjectGUID
    #   the SID
    #   the SamAccountName
    
    # Use a Hasttable object for fast lookup
    $currentMembers = @{}
    Get-ADGroupMember -Identity $groupName | Where-Object { $_.objectClass -eq 'user' } | ForEach-Object {
        # you could also use the SamAccountName, but they are only unique within the same domain.
        # I'll use the DistinghuishedName because this is always unique in the forest
        # the Value of the entry is not important, we'll only use the Key.
        $currentMembers[$_.DistinghuishedName] = $true
    }
    
    $results = Get-ADUser -Filter * -SearchBase $ou | ForEach-Object {
        # test if the user is already a member by checking if the lookup Hashtable has that Key
        $userName = $_.Name
        if ($currentMembers.ContainsKey($_.DistinghuishedName)) {
            Write-Host "User $userName is already a member of group $groupName"
            $status = "User $userName is already a member"
        }
        else {
            try {
                # the user is not already a member, so add him/her to the group
                Add-ADGroupMember -Identity $groupName -Members $_.DistinghuishedName -ErrorAction Stop
                $status = "User $userName added successfully"
            }
            catch {
                # something went wrong..
                $status = "User $userName could not be added to group $groupName. Error: $($_.Exception.Message)"
            }
        }
    
        # output a PsCustomObject that gets collected in the $results variable
        [PsCustomObject]@{
            'UserName'  = $userName
            'GroupName' = $groupName
            'TimeStamp' = Get-Date
            'Status'    = $status
        }
    }
    # output on console
    $results | Format-Table -AutoSize
    
    # Export to CSV file
    $results | Export-Csv C:\PS\AddADGroupToUsers.csv -NoTypeInformation
    

    【讨论】:

    • 这不起作用。我已经编辑了我的原始帖子以显示错误并且输出错误。
    • 仅供参考,我也尝试了上面的不同代码,效果很好,但需要很长时间,而不是你的代码需要几秒钟。我不知道如何加快速度。
    • @RobPowell 您可以通过为 $currentMembers 而不是数组创建哈希表并检查每个用户 DN 是否是该哈希中的键来加快速度。当然,依赖异常的代码要快得多。我现在在手机上。明天将为查找哈希表添加代码,以便您对其进行测试。
    • @RobPowell 我已经编辑了我的答案,现在使用(更快)查找 Hashtable 对象。这应该会提高处理速度。对于Add-ADGroupMember 可能引发的任何其他错误,我已插入try{..} catch{..} 块。
    • 这跑了 7 分钟,找不到任何东西。所以脚本运行,没有输出到主机,它创建了一个空的 .csv。我很想放弃,只是接受一个廉价而肮脏的添加而无需验证
    猜你喜欢
    • 2017-11-25
    • 1970-01-01
    • 2014-06-18
    • 2012-11-25
    • 1970-01-01
    • 2023-03-21
    • 1970-01-01
    • 2013-11-09
    • 2014-12-18
    相关资源
    最近更新 更多