sergey vasin

The IT blog

Создаем HTML-отчет для групп распространения Exchange – Hey, Scripting Guy! Blog

leave a comment »

Резюме: Генерация html-отчета для групп распространения (Distribution Groups) Microsoft Exchange Server 2010.

Microsoft Scripting Guy, Ed Wilson на связи. Сегодня я хочу представить вам нового приглашенного блогера: Serkan Varoğlu.

Serkan Varoğlu это Windows PowerShell-энтузиаст и Microsoft Exchange Server-фанатик. О себе он говорит: «Я обычный IT-pro, который любить делиться своими знаниями с сообществом». Он ведет блог по Microsoft Exchange Server на турецком языке (http://www.get-mailbox.org). Его Twitter на английском — @SRKNVRGL. Можете свободно к нему обращаться.

Создаем отчеты для Exchange

Я всегда ненавидел экспортировать данные для создания отчетов вручную. И я думаю, что я не один такой, кому не нравится тратить кучу времени для получения отчета. Как консультант, я также знаю, что если у клиента нет средств на покупку ПО для создания отчетов, единственная вещь, которую я могу для него сделать – это создать для них отчеты вручную. Один из наиболее востребованных отчетов – это получение списка членов групп распространения для некоторых групп с высокой степенью вложенности (nested groups). Давайте признаем, Microsoft Exchange Server не обладает встроенной возможностью создания отчетов, несмотря на то, что это лучшая платформа для работы с электронной почтой. Поэтому я подумал, что мне стоит создать PowerShell-скрипт, чтобы помочь клиентам с этой задачей.

Я написал PowerShell­-скрипт Report-DistributionGroupMember, который создает отличный html-отчет. Вы можете найти его в TechNet Script Repository в категории Exchange 2010.

01

Я хотел представить в отчете следующие данные:

  • Имеет ли группа распространения другие группы распространения в качестве членов, и если так то какая группа входит в какую группу?
  • Есть ли пустые группы?
  • Дублированные получатели, входящие в разные группы
  • Список уникальных получателей, которые получат сообщение, отправленное на адрес группы

Я собирался получить всю информацию в одном цикле, но это сильно усложняло скрипт. Вместо этого, я решил написать функцию, которая получает имена всех групп, входящих в группу распространения, и после этого проверяет каждую из полученных групп на наличие в них групп распространения и т.д., пока я не получу имена всех групп, входящих в изначальную группу распространения.

В этой функции я помещаю данные в две хеш-таблицы: $NestedGroup и $NestedGroups. Причина в том, что $NestedGroup перезаписывается в каждом цикле, а $NestedGroups сохраняет все данные. Кроме того, я в конце я делаю ее глобальной переменной. Это означает, что после завершения работы скрипта, я смогу получить эти данные в течение этой сессии, а также использовать их для более детального анализа.

function collect($DistGroupMembers)

{

$NestedGroup = @{}

if ($DistGroupMembers)

{

foreach ($member in $DistGroupMembers)

{

if(($member.RecipientTypeDetails -like «*Group*») -and ($member.RecipientTypeDetails -notlike «*Dynamic*»))

{

$name = $member.SamAccountName.ToString()

if ($NestedGroup.ContainsKey($name) -eq $false)

{

$NestedGroup.Add($name,$member.DisplayName.ToString())

$NestedGroups.Add($name,$DistGroup.Name.ToString())

}

}

}

}

if($NestedGroup.Values.Count -gt 0)

{

foreach ($NestedGroup in $NestedGroup.values)

{

$DistGroup = Get-DistributionGroup $NestedGroup

$Nest=Get-DistributionGroupMember $NestedGroup

collect $Nest

}

}

$global:NestedGroups=$NestedGroups

}

В этой функции есть один изъян. Если некая группа распространения входит в родительскую группу несколько раз (например, она является членом нескольких дочерних групп изначальной группы), скрипт не сможет добавить все ее вхождения в переменную $NestedGroups. Но вообще-то мне и не нужно, чтобы одна и та же группа указывалась несколько раз, так что для меня это плюс. Также я указал в переменной $ErroractionPrefence значение «silentlycontinue», чтобы в случае ошибок пользователь не получал множество строк красного текста.

Теперь, когда моя функция готова, мне нужно имя родительской группы распространения. Она будет указываться пользователем. И именно ее я укажу в качестве параметра для функции.

param ( [Parameter(Position=0,Mandatory=$true,ValueFromPipeline=$true,HelpMessage=’Distribution Group Name’)][string]$Name)

$DistGroup = $ADistGroup = Get-DistributionGroup $Name -ErrorAction «silentlycontinue»

if(!$DistGroup)

{

«Could not retrieve any information from your input. Please make sure Distribution Group Name is correct.»

exit

}

$DistGroupMembers = Get-DistributionGroupMember $DistGroup -Resultsize Unlimited

collect $DistGroupMembers

Теперь мне нужно получить SamAccountName для каждой группы в $NestedGroups и добавить эту информацию каждому соответствующему участнику $NestedGroups. Также мну нужно определить и записать информацию – является ли группа пустой.

foreach ($DistGroup in $NestedGroups.keys)

{

$DistGroup = Get-DistributionGroup $DistGroup

$AllDistGroups += $DistGroup

$srknvrgl=Get-DistributionGroupMember $DistGroup -Resultsize Unlimited

if ($srknvrgl)

{

foreach ($srkn in $srknvrgl)

{

$srkn | Add-Member -type NoteProperty -name GroupName -value $DistGroup.SamAccountName

$srkn | foreach {$MemberCount[$_.SamAccountName] += 1}

}

}

else

{

$EmptyGroup+=$DistGroup

}

$AllMembers+=$srknvrgl

На данный момент у меня есть:

  • Хеш-таблица, содержащая имена всех групп распространения и имена их родительских групп в качестве значений ($NestedGroups)
  • Все пустые группы ($EmptyGroup)
  • Еще одна хеш-таблица, содержащая участников групп и количество их вхождений в родительскую группу, как явных так и неявных ($MemberCount)
  • А также все участники родительской группы ($AllMembers). Но есть один нюанс – в переменную $AllMembers также входят группы распространения, расположенные на втором уровне вложенности. Мы избавимся от них при построении отчета.

Я хочу, чтобы отчет сообщал обо всех дублированных получателях, поэтому мне нужно получить значения переменной $AllMembers, соответствующие строкам хеш-таблицы $MemberCount, значение которых больше 1. Значение больше 1 означает что получатель встречается более одного раза.

foreach ($DuplicateMember in $MemberCount.keys)

{

if ($MemberCount.$DuplicateMember -gt 1)

{

$DuplicateMemberGroup+=$AllMembers | ?{$_.SamAccountName -like $DuplicateMember}

}

}

Готово. Теперь я обладаю всей нужной информацией и можно начинать строить отчет.

Это довольно просто. Я использовал только одну переменную ($Output) для хранения всех html-данных, которые я добавлял в нее по мере работы скрипта. Все что мне нужно было сделать, это наполнять ее информацией таким образом, чтобы отчет не потерял стиля. Я не буду объяснять весь html-код в этом PowerShell-скрипте, поскольку его объем превышает 180 строк, но я покажу как я указывал информацию о стилях. В таблицах html я использовал if-else и foreach. Если вы посмотрите на код, то увидите, что все что они делают, в основном касается стиля.

В принципе, все что я сделал – это довольно просто. Я создал таблицы html и заполнял их полученными ранее данными при помощи foreach. Если переменная содержала данные и значение соответствовало искомому – я добавлял нужный мне стиль. Если нет – я указывал стиль по умолчанию. Чуть ниже приведен пример скрипта.

Заметка: Для каждой группы я проверял свойство MemberJoinRestriction. Если значение было «Open», фон ячейки становился зеленым. Если «Approval» — оранжевым. В другом случае цвет фона не указывался. Также, если значение свойства MemberDepartRestriction было «Open», граница ячейки состояла из красных точек. Поэтому сначала я указал необходимую информацию о стиле в переменных $bgcolor и $border – цвет фона и стиль границы, соответственно.

if ($groupdata.MemberJoinRestriction -like «Open»)

{$bgcolor=»bgcolor=»»#A4FFA4″»»}

elseif ($groupdata.MemberJoinRestriction -like «Approval*»)

{$bgcolor=»bgcolor=»»#FFB366″»»}

else

{$bgcolor=»»}

if ($groupdata.MemberDepartRestriction -like «Open»)

{$border=»style=»»border: 2px dotted red»»»}

else

{$border=»»}

Стили готовы, теперь я могу создать ряд в таблице:

$Output+=»

   

«

Таким образом я достаточно просто создал стили для html-таблицы.

Теперь, когда переменная $output полностью заполнена, пора выгрузить ее в html-файл, и если пользователь не указал желаемого имени для файла в параметре $ReportName, мы сами сгенерируем для него уникальное имя. Наиболее простой для меня способ генерации уникального имени – это использовать в имени файла текущее время.

$t = Get-Date -UFormat %d%m%H%M

If (!$ReportName)

{

$HTMLReport = «$($ADistGroup.windowsemailaddress.local)-$($t).html»

}

Else

{

$HTMLReport=$ReportName

}

Windows PowerShell-скрипт готов. Приношу извинения за то, что не сделал описание каждой строки кода, моей целью было поделиться с вами основной идеей по созданию html-отчета. Полный текст скрипта вы можете найти в TechNet Script Repository в категории Exchange 2010. Перед тем как передать слово Эду, хочу вам сказать, что я не добавил к этому решению динамические группы распространения (Dynamic Distribution Groups), при построении отчета они отбрасываются. Я надеюсь, вам понравилось. Если у вас возникли какие-то вопросы – напишите мне в твиттер @SRKNVRGL.

Автор:

Ed Wilson, Microsoft Scripting Guy

Оригинал:

http://blogs.technet.com/b/heyscriptingguy/archive/2012/11/19/generate-html-report-for-exchange-distribution-group-members.aspx


Страницы в социальных сетях:

Twitter: https://twitter.com/vsseth
Facebook: https://fb.com/inpowershell
VKontakte: https://vk.com/inpowershell


Реклама

Written by Сергей Васин

Ноябрь 23, 2012 в 11:16

Опубликовано в HeyScriptingGuyBlog, PowerShell

Tagged with

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s