Исправление try / catch и вывода - PullRequest
1 голос
/ 14 октября 2019

Я добавляю OU пользователей в группу и хочу записать:

  1. Пользователи добавлены
  2. Пользователи, уже включенные в список
  3. , выводят вышеуказанноев файл

Текущий код ниже работает и выводит:

UserName              GroupName                          TimeStamp
--------              ---------                          ---------
%Username%            %groupname%                        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. Имеет ли значение, что это DistinghedName, а не, может быть, $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

Так что, отойдя от кода Тео, я попробовал предложение Ивана, но это занимает ДЛИННОЕ время:

# 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
    }
}

Это работает, я думаю, ноПотребовалось несколько минут, чтобы получить 3 результата из 7, тогда как оригинальный код работал в считанные секунды. Изменить: Код завершен, и написал для размещения предупреждения. Я знаю, что могу настроить часть статуса, чтобы добавить ошибку в статус. Просто не стоит так долго!

Метки времени были разделены секундами, но теперь:

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

Ответы [ 2 ]

3 голосов
/ 14 октября 2019

Блок 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 для обработки любых ошибок, которые могут возникнуть.

0 голосов
/ 15 октября 2019

Хотя я никогда раньше не видел, чтобы Add-ADGroupMember НЕ выбрасывал исключение Add-AdGroupMember : The specified account name is already a member of the group раньше, Иван МИРЧЕВ сообщает, что в его среде нет никаких исключений при попытке добавить пользователяэто уже член группы.

Если это действительно так в некоторых средах, то доверять этому исключению больше не является хорошей идеей, и нам нужно сделать дополнительный шаг, сначала получив списоквсе текущие члены группы.
Этот дополнительный шаг, конечно, приведет к увеличению времени обработки.

# 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
...