Не удается добавить элементы в массив Powershell

#arrays #powershell #active-directory #exchange-server

#массивы #powershell #active-directory #exchange-сервер

Вопрос:

Я относительно новичок в Powershell, но не смог найти ответ в Интернете.

Я пытаюсь получить количество электронных писем на одного отключенного пользователя в Exchange 2010, но также необходимо получить заголовок пользователя в форме AD, поскольку организация группирует пользователей по типу, используя атрибут Title в AD

Я написал следующее, но я не могу получить нужные мне данные, он просто возвращает длину и числа в файл CSV, например «длина» «10» «3» «34»

Если я оставлю $title из присвоения $Disabled = имя пользователя и количество элементов добавляются в файл CSV, но мне действительно нужен заголовок. Может кто-нибудь указать, где я ошибаюсь.

 Import-Module ActiveDirectory

$i=0

$disUsers = Get-ADUser -Filter * -SearchBase "ou=User Disabled Accounts,dc=test,dc=com" -Properties SamAccountName,Title

$Disabled = @()

$disUsers | Foreach-Object{      
    $sam = $_.SamAccountName
    $title = $_.Title
    $mailDetail=Get-MailboxStatistics $sam | Select -Property DisplayName,ItemCount
    $Disabled  = $title, $mailDetail
    $i  ;   
 }


$Disabled | Export-Csv -Path $env:userprofiledesktopDisabledADUserTitlewithMailbox.csv -NoTypeInformation
  

К сожалению, работа с кодом, предоставленным Стивом, приводит к следующим ошибкам

 Exception calling "Add" with "2" argument(s): "Item has already been added. Key in dictionary: 'ADCDisabledMail'  Key being added: 'ADCDisabledMail'" ...     

Exception calling "Add" with "2" argument(s): "Key cannot be null. Parameter name: key"...
  

Редактировать
С помощью Стивена я смог заставить это работать со следующим

 'Import-Module ActiveDirectory' 

$i=0

$disUsers=Get-ADUser -Filter {mailNickName -like '*'} -SearchBase "ou=User Disabled Accounts,dc=test,dc=com" -Properties SamAccountName,Title 

$dis2 = $disUsers.count

$DisabledUser = @()

$disUsers | Foreach-Object{

Write-Host "Processing record $i of $dis2"

                $sam = $_.SamAccountName

                $title = $_.Title

$mailDetail=Get-MailboxStatistics $sam | Select-Object DisplayName, @{ Name = 'Title'; Expression = {$title}}, ItemCount  

                                $DisabledUser = $mailDetail
  $i  ;   

}

$DisabledUser | Export-Csv -Path $env:userprofiledesktopDisabledADUserTitlewithMailbox.csv -NoTypeInformation
  

Комментарии:

1. Ваш CSV содержит только Length , потому что вы отправляете только строки в Export-Csv . Export-Csv просматривает первый объект в конвейере и принимает его свойства в качестве заголовков для файла CSV. Затем извлекает значение каждого свойства и выводит их для каждого объекта (по одному объекту в строке). Строка имеет только Length свойство. Итак, результат, который вы видите, ожидаемый.

2. Спасибо @AdminOfThings за объяснение.

Ответ №1:

Похоже, что вы действительно пытаетесь связать данные для создания небольшого отчета. Вы имеете дело с данными, поступающими из разных команд, поэтому вам нужно свойство для объединения. В этом случае я бы посмотрел на атрибут AD legacyExchangeDN и свойство LegacyDN , возвращаемое Get-MailboxStatistics . Код может выглядеть примерно так:

 $DisabledUsers = @{}

Get-ADUser -SearchBase 'ou=User Disabled Accounts,dc=test,dc=com' -Filter * -Properties 'Title','legacyExchangeDN' |
ForEach-Object{ $DisabledUsers.Add( $_.legacyExchangeDN, $_ ) }

$DisabledUsers.Values.SamAccountName | 
Get-MailboxStatistics |
Select-Object DisplayName, ItemCount, @{ Name = 'Title'; Expression = { $DisabledUsers[$_.LegacyDN].Title } }
  

Это приведет к выводу чего-то вроде:

 DisplayName   ItemCount Title
-----------   --------- -----
Mr. Smith        113576 Executives
  

Если вы предпочитаете, чтобы он переходил непосредственно в файл CSV, просто добавьте Export-CSV команду после Select-Object команды, как показано ниже:

 $DisabledUsers = @{}

Get-ADUser -SearchBase 'ou=User Disabled Accounts,dc=test,dc=com' -Filter * -Properties 'Title','legacyExchangeDN' |
ForEach-Object{ $DisabledUsers.Add( $_.legacyExchangeDN, $_ ) }

$DisabledUsers.Values.SamAccountName | 
Get-MailboxStatistics |
Select-Object DisplayName, ItemCount, @{ Name = 'Title'; Expression = { $DisabledUsers[$_.LegacyDN].Title } } |
Export-CSV -Path $env:userprofiledesktopDisabledADUserTitlewithMailbox.csv -NoTypeInformation
  

Я бы использовал Get-User из командной строки Exchange, однако у нее нет legacyExchangeDN в качестве возвращаемого свойства. У него есть sAMAccountName , но его использование вынудило бы меня соединить все Get-Mailbox . В любом случае, это очень распространенный метод использования хэш-таблицы для ссылки на связанные значения в другой коллекции.

Я уверен, что потребуется некоторая дополнительная работа, чтобы получить правильный отчет.

Кроме того, старайтесь избегать использования = оператора для добавления массивов. Лучший способ получить массив — позволить PowerShell предоставить его, как я сделал выше. Однако, если вы не можете обойти это, наиболее распространенной альтернативой является ArrayList. Как и в большинстве случаев, есть несколько способов сделать это, ниже приведен всего 1 пример.

 # To create:
$ArrList = [Collections.ArrayList]@()

#To Add a value:
[Void]$ArrList.Add( 'ValueOrObjectHere' )
  

Примечание: Документация / обсуждение = и ArrayList легко доступны
найдите с помощью компьютера Google…

Обновить:

Устранение ошибок, отмеченных в самой последней правке:

Первая ошибка в принципе невозможна. Простите меня, но я должен предположить, что вы допустили какую-то ошибку, вызвавшую эту ошибку. legacyExchangeDN всегда должен начинаться с '/o=...' , и их ключом, на который ссылается ошибка, было ‘ADCDisabledMail’ . Кроме того, LegacyExchangeDNs, естественно, уникальны в Active Directory, поэтому почти нет шансов, что у вас будет дубликат. Таким образом, я не прилагал никаких усилий, и ни одно из них не гарантировано, для предотвращения такой маловероятной ошибки.

Примечание: Если вы повторно тестируете код, вам придется воссоздавать хэш, $DisabledUsers = @{} иначе хэш будет существовать с предыдущего запуска, и повторяющиеся ключевые ошибки неизбежны…

Вторая ошибка «ключ не может быть нулевым» может быть связана с тем, что учетные записи AD, не включающие почтовые ящики, в указанном подразделении фактически приводят к тому, что атрибут legacyExchangeDN имеет значение null для этих пользователей. Следовательно, нулевой ключ…. Этого можно избежать, изменив фильтр, чтобы возвращать только пользователей с поддержкой почты:

 $disUsers = Get-ADUser -Filter  { mailNickName -like '*' } -SearchBase "ou=User Disabled Accounts,dc=test,dc=com" -Properties SamAccountName,Title
  

Примечание: Для справки, mailNickName обычно является псевдонимом propertry
возвращается с Get-Mailbox

Комментарии:

1. Спасибо за вашу помощь, я попробовал ваше решение, но оно выдает следующие ошибки, и результирующий CSV-файл пуст. Я добавил ошибки в свой первый пост в качестве редактирования, поскольку раздел комментариев не будет принимать полную ошибку

2. Спасибо @Steven, код был выполнен, как указано, и возвращены ошибки. Я понимаю, что вторая ошибка может быть связана с отсутствием пользователей с поддержкой почты, я новичок в организации, и мне сообщили, что у всех была включена почта.

3. Я ценю то, что вам сказали, но вы можете легко подтвердить это, отключив фильтр ; -Filter { mailNickName -notlike '*' } . Это сообщит вам, есть ли в данном подразделении пользователи, не являющиеся почтовыми ящиками. Примечание: legacyExchangeDN является обязательным свойством в среде Exchange. Если бы это было действительно null, у вас были бы всевозможные другие проблемы. Я чего-то не понимаю; вы используете Office 365? Можете ли вы попробовать выполнить запрос без добавления в хэш-таблицу? Также запустите отрицательный фильтр, как описано, и дайте мне знать, что возвращается. Примечание: Код отлично работает в моей среде…

4. Привет @Steven извините за задержку, я столкнулся с другой проблемой. Организация доступна только для Exchange, но мы используем Office 365 для Outlook и других приложений Office. Мне не удалось успешно запустить ваш код, но я смог воспользоваться идеей и изменить свой исходный код, чтобы получить то, что мне было нужно, я включил это в редактирование моего вопроса, так что большое спасибо. Что касается значения ADCDisabledMail для legacyExchangeDN, я изучаю это, это может быть из предыдущего обновления Exchange, и, поскольку мы скоро снова обновим его, я обязательно проверю.

5. Я рад, что это сработало! Урок важнее, чем то, работал ли мой конкретный код в вашей среде.