Список пользователей, использующих мобильные устройства для получения почты.

images11 Поступила очередная задача от любимого клиента. Предоставить список пользователей, использующих мобильные устройства на базе Windows Mobile для синхронизации с Exchange. Период – месяц. Задумался, видимо опять выручит PowerShell. Сказано – сделано. При помощи коллег Александра Романова и Илгиза Мамышева задачу выполнить удалось. Не совсем так, как хотелось, но тем не менее. Список получен, форматирование доводилось вручную. Итак, методика получения списка.

Начнем с основ. Вся информация о настроенных мобильных устройствах хранится в почтовом ящике пользователя. Пользователь, имеющий мобильное устройство, синхронизирующееся с использованием ActiveSync имеет значение параметра HasActiveSyncDevicePartnership = $true. Именно по этому параметру рекомендуется сделать отбор пользователей. Чтобы не запрашивать свойства всех почтовых ящиков. Для этих целей мы использовали командлет Get-CASMailbox, в выводе которого и можно увидеть данный параметр.

Для получения информации об устройстве, а именно версии операционной системы и времени последней удачной синхронизации, мы используем командлет Get-ActiveSyncDeviceStatistics. В качестве определителя ему необходимо значение параметра Mailbox, которое имеет тип Microsoft.Exchange.Configuration.Tasks.MailboxIdParameter, такой же как тип значений параметра Identity в Get-CASMailbox.

Итак, сначала объявим переменную, $Mailbox, содержащую ящики, отфильтрованные по значению параметра HasActiveSyncDevicePartnership, откуда мы будем брать значения различных параметров, а именно Name (Имя пользователя) и Identity (для передачи на вход параметра Mailbox командлета Get-ActiveSyncDeviceStatistics):

$Mailbox = Get-CASMailbox | where {$_.HasActiveSyncDevicePartnership –eq $true

Далее. берем эту переменную и загоняем в конвеер, и для каждого значения выполняем Get-ActiveSyncDeviceStatistics, форматируя вывод в таблицу с полями DeviceUserAgent и LastSuccessSync. Примерно так:

$Mailbox | foreach {Get-ActiveSyncDeviceStatistics –Mailbox $_.Identity} |ft DeviceUserAgent,LastSuccessSync

На выходе получим:

DeviceUserAgent                         LastSuccessSync
—————                         —————
NokiaE51/2.05(3)MailforExchange         15.01.2009 17:23:52
Apple-iPhone/508.11                     31.05.2009 11:59:15
Apple-iPhone/506.136                    30.10.2008 12:34:19
MSFT-PPC/5.1.2000                       19.05.2008 15:28:48
Apple-iPhone/503.1                      02.10.2008 14:22:54
Apple-iPhone/701.25900007               02.06.2009 7:25:59
MSFT-PPC/5.2.402                        24.04.2009 19:25:48
MSFT-PPC/5.2.0                          04.09.2007 18:20:46
NokiaE90/1.0                            26.05.2009 11:02:54
TestActiveSyncConnectivity              26.03.2009 8:10:59
Apple-iPhone/507.77                     15.12.2008 4:35:13

 

Теперь нам нужно сопоставить полученные данные с пользователями. И здесь меня ждет засада. Дело в том, что нет ни одного совпадающего параметра вывода в этих двух командлетах, чтобы их связать. Поэтому я решил запросить значение NAME из командлета Get-CASMailbox, и его добавить в вывод. Для этого я добавил в начало цикла вывод параметра Name из переменной. И дополнительное поле в Format Table. Получил такую строку:

$Mailbox | foreach {$_.Name; Get-ActiveSyncDeviceStatistics –Mailbox $_.Identity} |ft Name,DeviceUserAgent,LastSuccessSync

В результате получили вывод:

Иванов Иван Иванович

Name                       DeviceUserAgent            LastSuccessSync
—-                       —————            —————
                           NokiaE51/2.05(3)Mailfor… 15.01.2009 17:23:52
                           Apple-iPhone/508.11        31.05.2009 11:59:15
                           Apple-iPhone/506.136       30.10.2008 12:34:19
                           MSFT-PPC/5.1.2000          19.05.2008 15:28:48
Петров Петр Петрович
                           Apple-iPhone/503.1         02.10.2008 14:22:54
                           Apple-iPhone/701.25900007  02.06.2009 7:25:59
                           MSFT-PPC/5.2.402           24.04.2009 19:25:48
                           MSFT-PPC/5.2.0             04.09.2007 18:20:46
Семенов Семен Семенович
                           NokiaE90/1.0               26.05.2009 11:02:54
MyTestUser
                           TestActiveSyncConnectivity 26.03.2009 8:10:59
Васильев Василий Васильевич
                           Apple-iPhone/507.77        15.12.2008 4:35:13

Странность. Имя первого пользователя вывелось выше названия поля, и не на одном уровне с данными устройства, но это уже что-то.

Далее, очень хотелось бы отделить устройства на базе Windows Mobile от других. Для этого я добавил фильтр по началу значения параметра DeviceUserAgent (MSFT*), получилось вот так:

$Mailbox | foreach {$_.Name; Get-ActiveSyncDeviceStatistics –Mailbox $_.Identity} | where {$_.DeviceUserAgent –like ‘MSFT*’} |ft Name,DeviceUserAgent,LastSuccessSync

И вот вывод мне не понравился:

Name                       DeviceUserAgent            LastSuccessSync
—-                       —————            —————
                           NokiaE51/2.05(3)Mailfor… 15.01.2009 17:23:52
                           Apple-iPhone/508.11        31.05.2009 11:59:15
                           Apple-iPhone/506.136       30.10.2008 12:34:19
                           MSFT-PPC/5.1.2000          19.05.2008 15:28:48
                           Apple-iPhone/503.1         02.10.2008 14:22:54
                           Apple-iPhone/701.25900007  02.06.2009 7:25:59
                           MSFT-PPC/5.2.402           24.04.2009 19:25:48
                           MSFT-PPC/5.2.0             04.09.2007 18:20:46
                           NokiaE90/1.0               26.05.2009 11:02:54
                           TestActiveSyncConnectivity 26.03.2009 8:10:59
                           Apple-iPhone/507.77        15.12.2008 4:35:13

Начисто исчезли значения поля Name. И вот сколько я над этим не бился – ничего у меня не получилось. Сказывается неумение составлять циклы и отсутствие базовых знаний по программированию.

В общем взял я предыдущий вывод, открыл его в Excel и ручками отформатировал. Благо подавляющее большинство устройств – Apple iPhone, соответственно устройств на Windows Mobile было немного.

P.S. Позже, читая о командлетах ActiveSync я наткнулся на описание схожей задачи: http://exchangepedia.com/blog/2008/06/exchange-server-2007-listing-activesync.html, но мне это не подошло, а времени на подгонку уже не было.

P.P.S. Я с удовольствием выслушаю Вашу критику, предложения и замечания по оптимизации. Особенно то, что касается форматирования. И, естественно, с интересом жду комментариев от наших гуру PowerShell Васи Гусева и Vadims Podans :)

Реклама
Список пользователей, использующих мобильные устройства для получения почты.

Список пользователей, использующих мобильные устройства для получения почты.: 8 комментариев

  1. Похоже, вывод параметра DeviceUserAgent для каждого пользователя надо в массив выводить. Правда, задача это не тривиальная. Надо Васю ждать =)

  2. Олег Крылов:

    Ждем Васю или Вадима. Мне бы еще сортировку по времени сделать. И если в списке устройств у одного пользователя больше одного устройства, хотелось бы, чтобы показывало только то, которое синхронизировалось последним.

  3. я тут мимо пробегал. На счёт пустой колонки с именами в последнем варианте, то там проблема вот в чём:

    $Mailbox | foreach {$_.Name; Get-ActiveSyncDeviceStatistics –Mailbox $_.Identity}

    по концепции конвейера, в нём в любой момент времени не может быть больше 1 объекта. Т.е. данные по конвейеру передаются поштучно. А у вас за 1 итерацию цикла генерируется 2 объекта:
    $_.name и Get-ActiveSyncDeviceStatistics –Mailbox $_.Identity. Format-Table с ними разберётся спокойно, поскольку он просто форматирует вывод. Но его потрясаяющая работа (Format-Table может делать потрясающие вещи) создаёт ощущение, что одна строчка — это вывод составленный из одного объекта, а на самом деле — 2. А во втором примере вы делаете вот что:

    where {$_.DeviceUserAgent –like ‘MSFT*’}

    и через этот фильтр пройдёт только вывод команды Get-ActiveSyncDeviceStatistics –Mailbox $_.Identity, поскольку у объекта $_.name нету свойства DeviceUserAgent и, следовательно, объекты $_.name будут отфильтрованы всегда.

    Сейчас немного разгребусь у себя, попробую что-то сваять для вас.

  4. как вариант:
    $Mailbox | foreach {
    $name = $_.Name
    Get-ActiveSyncDeviceStatistics –Mailbox $_.Identity | ?{$_.DeviceUserAgent -like «MSFT*»} | ft @{l=»UserName»;e={$name}}, DeviceUserAgent, LastSuccessSync
    }

    тут есть одна трудность, что из-за цикла foreach не получится так просто сделать вывод в одну таблицу, а для каждой итерации будет своя таблица. Пока ничего умного на ум не приходит.

  5. Олег, принимай работу. Комменты ниже по тексту.
    ======================================
    $Mailbox = Get-CASMailbox | where {$_.HasActiveSyncDevicePartnership –eq $true}

    $Table = New-Object System.Management.Automation.PSObject #Создаль массив
    $Table | Add-Member NoteProperty «UserName» ($null) #Создали поля
    $Table | Add-Member NoteProperty «SyncTime» ($null)
    $Table | Add-Member NoteProperty «Device» ($null)
    «UserName,SyncTime,Device»>C:\Table.txt #Инициируем файл. Создаем шапку таблицы

    #Понеслась.. Цикл в цикле — объединяем две таблицы (майлбоксы и девайсы) в одну.
    $Mailbox | foreach { $i++
    $name=$_.DisplayName;
    $array1=Get-ActiveSyncDeviceStatistics -Mailbox $_.Identity;
    $array1 | foreach {
    $Table.UserName=»$name»
    $Table.SyncTime=»$($_.lastsuccesssync)»
    $Table.Device=»$($_.deviceuseragent)»
    #$Table #Можно вывести на экран для «просто посмотреть»
    «»+$Table.UserName+»,»+$Table.SyncTime+»,»+$Table.Device>>C:\Table.txt #Не пришло на ум как обойтись без вынрузки в файл. Тут собираем данные для массива.
    }
    }

    $Table = Import-Csv C:\Table.txt #Загрузили массив из файла
    $str=»» #Инициируем вспомогательную переменную
    «UserName,SyncTime,Device»>C:\Table.txt #Инициируем файл. Создаем шапку таблицы. (старое содержимое не нужно)
    #Сортируем массив по полю SyncTime по убыванию и перебираем результат. Отбираем для записи в файл только неповторяющиеся записи по полю UserName.
    #В итоге получаем список-массив с одним вхождением по UserName и последним значением поля SyncTime (т.е. запись о последней синхронизации девайса пользователя).
    $Table | Sort-Object -Property SyncTime -Descending |
    foreach { if ($str -notmatch $_.UserName) {$str+=$_.UserName; «»+$_.UserName+»,»+$_.SyncTime+»,»+$_.Device>>C:\Table.txt} }

    $Table = Import-Csv C:\Table.txt #Загрузили массив из файла
    #$Table #Выводим результат на экран
    $Table>C:\Table.txt #Выводим результат в файл
    C:\Table.txt
    Remove-Item -path C:\Table.txt #Чистим за собой

    Write-Host «Олег, с тебя пиво»

  6. Олег Крылов:

    Ух ты! Илгиз, молодчина! Сегодня вечером проверю. Пиво за мной не заржавеет :)
    А Вася только поржать в соседнем посте смог, нет бы помочь :)

  7. # Почистил рудименты от неудавшегося функционала
    #############################
    #ver 1.1
    #
    #Получаем список майлбоксов
    $Mailbox = Get-CASMailbox | where {$_.HasActiveSyncDevicePartnership –eq $true}

    «UserName,SyncTime,Device»>C:\Table.txt #Инициируем файл. Создаем шапку таблицы

    #Цикл в цикле — перебираем майлбоксы и по каждому получаем список девайсов, объединяем майлбоксы и девайсы в одну таблицу.
    $Mailbox | foreach { $i++
    $name=$_.DisplayName;
    $array1=Get-ActiveSyncDeviceStatistics -Mailbox $_.Identity;
    $array1 | foreach {
    #Не пришло на ум как обойтись без выгрузки в файл. Тут собираем данные для массива.
    «»+$name+»,»+$($_.lastsuccesssync)+»,»+$($_.deviceuseragent)>>C:\Table.txt
    }
    }

    $Table = Import-Csv C:\Table.txt #Загрузили массив из файла
    $str=»» #Инициируем вспомогательную переменную
    «UserName,SyncTime,Device»>C:\Table.txt #Инициируем файл. Создаем шапку таблицы. (старое содержимое не нужно)
    #Сортируем массив по полю SyncTime по убыванию и перебираем результат. Отбираем для записи в файл только неповторяющиеся записи по полю UserName.
    #В итоге получаем список-массив с одним вхождением по UserName и последним значением поля SyncTime (т.е. запись о последней синхронизации девайса пользователя).
    $Table | Sort-Object -Property SyncTime -Descending |
    foreach { if ($str -notmatch $_.UserName) {$str+=$_.UserName; «»+$_.UserName+»,»+$_.SyncTime+»,»+$_.Device>>C:\Table.txt} }

    $Table = Import-Csv C:\Table.txt #Загрузили массив из файла
    #$Table #Выводим результат на экран
    $Table>C:\Table.txt #Выводим результат в файл
    C:\Table.txt

    Remove-Item -path C:\Table.txt #Чистим за собой

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

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

Логотип WordPress.com

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

Google+ photo

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

Фотография Twitter

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

Фотография Facebook

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

w

Connecting to %s