PowerShell: Создаём контакты в Outlook пакетом–из AD, csv, и не только
Продолжаю тему пакетной обработки пользователей.На этот раз возникла потребность создать в Outlook карточки контактов по данным учётных записей пользователей. Причём не важно – берём данные из .csv файла или из AD. Решим простую на первый взгляд задачу.
Первым делом полез в сеть и нашёл массу примеров кода для решения данной задачи разной степени сырости. Лучшую заготовку нашёл у xaerg:
$outlook = New-Object -ComObject Outlook.Application $mapi = $outlook.GetNamespace("MAPI") $Contacts = $mapi.GetDefaultFolder(10) $OU = [ADSI]"LDAP://OU=Contacts,OU=Test,DC=Domain,DC=local" $selector = New-Object system.DirectoryServices.DirectorySearcher $Selector.SearchRoot = $OU $selector.Filter = '(objectClass=Contact)' $selector.FindAll() ` | % { $Contact = $outlook.Application.CreateItem(2) $Contact.LastName = $_.Properties.sn $Contact.Email1Address = $_.Properties.mail $Contact.Save() }
Естественно – это просто заготовка, к тому же приведённый код частично обрабатывает только контакты из AD, а не учётные записи пользователей.
Можно пытаться дорабатывать вышеприведённый код, но он сильно далёк он от PoSh стиля. А хочется иметь такой вот код для импорта контактов из .csv файла:
<# .Synopsis Загружает данные сотрудников из .csv файла, создаёт по эти данным конткты Outlook .Description Загружает данные сотрудников из .csv файла, создаёт по эти данным конткты Outlook .Example Импортируем .\UpdateUsersAttributes.ps1 -csvFile 'users.csv' #> [CmdletBinding( ConfirmImpact = 'Low', SupportsShouldProcess = $true )] param ( # Полный путь к файлу, из которого будем импортировать. [Parameter( Mandatory=$false, Position=0, ValueFromPipeline=$false )] [System.IO.FileInfo] $csvFile = ` (join-path ` -path ( ( [System.IO.FileInfo] ( $myinvocation.mycommand.path ) ).directory ) ` -childPath 'users.csv' ` ) ) Import-Module 'ITG.Outlook' -Prefix 'Outlook' -ErrorAction Stop; $users = @( ` get-content ` -path $csvFile ` | convertFrom-csv ` -UseCulture ` | New-OutlookContact -Force -PassThru ` | Select-Object Subject, EMail1DisplayName, EMail1Address ` | Out-GridView ` ;
или из AD:
<# .Synopsis Загружает данные сотрудников из AD, создаёт по эти данным конткты Outlook .Description Загружает данные сотрудников из AD файла, создаёт по эти данным конткты Outlook .Example Импортируем .\UpdateUsersAttributes.ps1 #> [CmdletBinding( ConfirmImpact = 'Low', SupportsShouldProcess = $true )] param ( # Полный путь к OU, из которого будем импортировать. [Parameter( Mandatory=$false, Position=0, ValueFromPipeline=$false )] [System.String] $OU = 'OU=Служба сбыта,OU=Научно-производственный дивизион,OU=Группа Компаний ГАРО,OU=Персонал,OU=Предприятия,OU=iTg,DC=novgaro,DC=ru' ) Import-Module ActiveDirectory; Import-Module 'ITG.Outlook' -Prefix 'Outlook' -ErrorAction Stop; Get-ADUser ` -Filter * ` -SearchBase $OU ` -SearchScope Subtree ` -Properties ` displayName, givenName, sn, initials, title, userPrincipalName, info, ` manager, ` company, department, ` co, countryCode, postalCode, st, l, streetAddress, ` telephoneNumber, facsimileTelephoneNumber, homePhone, ipPhone, mobile, otherTelephone, wWWHomePage, mail ` | New-OutlookContact -Force -PassThru ` | Select-Object Subject, EMail1DisplayName, EMail1Address ` | Out-GridView ` ;
Выше приведённый код прекрасно вписывается в идеологию PowerShell. Но, естественно, он подразумевает использование модуля, который и предоставляет нам командлеты – обёртки над объектами контактов в Outlook. Приведу код модуля ITG.Outlook. Репозиторий модуля размещён на github:
Add-Type ` -AssemblyName 'Microsoft.Office.Interop.Outlook' ` ; function Get-Contact { <# .Component Outlook.Application .Synopsis Возвращаем найденный контакт из папки контактов по умолчанию. .Description Возвращаем найденный контакт из папки контактов по умолчанию. .Example Get-Contact -Filter "[Subject]='Бетке Сергей Сергеевич'"; #> [CmdletBinding( SupportsShouldProcess=$true , ConfirmImpact="Low" )] param ( # Поисковый запрос в синтаксисе Outlook [Parameter( Mandatory=$false , ParameterSetName="Filter" )] [String] [AllowNull()] $Filter , # Фамилия [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="Properties" )] [System.String] [ValidateNotNullOrEmpty()] [Alias("sn")] [Alias("SecondName")] $LastName , # Имя [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="Properties" )] [System.String] [ValidateNotNullOrEmpty()] [Alias("givenName")] $FirstName , # Отчество [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="Properties" )] [System.String] $MiddleName ) begin { $Outlook = New-Object -ComObject Outlook.Application; $Contacts = $Outlook.GetNamespace('MAPI').GetDefaultFolder( [Microsoft.Office.Interop.Outlook.OlDefaultFolders]::olFolderContacts ).Items; } process { if ( $PSCmdlet.ParameterSetName -ne 'Filter' ) { $Filter = ( $PSBoundParameters.Keys ` | ? { $PSBoundParameters.$_ } ` | % { "[$_]='$($PSBoundParameters.$_)'" } ` ) -join ' AND '; }; if ( $Filter ) { Write-Debug "Осуществляем выборку контактов по фильтру $Filter"; for ( $Contact = $Contacts.Find( $Filter ); $Contact; $Contact = $Contacts.FindNext() ) { return $Contact; }; } else { $Contacts ` | % { return $_; }; }; } } function New-Contact { <# .Component Outlook.Application .Synopsis Создание нового контакта. .Description Создание нового контакта. .Example Get-Content ` -path $usersCsvFile ` | ConvertFrom-Csv ` -UseCulture ` New-Contact; #> [CmdletBinding( SupportsShouldProcess=$true , ConfirmImpact="Medium" )] param ( # Фамилия [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] [ValidateNotNullOrEmpty()] [Alias("sn")] [Alias("SecondName")] $LastName , # Имя [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] [ValidateNotNullOrEmpty()] [Alias("givenName")] $FirstName , # Отчество [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] $MiddleName , # Инициалы [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] $Initials , # логин (он же - lname для почты и так далее) [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] [Alias("mailNickname")] $NickName , # полное наименование контакта (используем ФИО) [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] [Alias("cn")] $Subject = ( ( $LastName, $FirstName, $MiddleName | ? { $_ } ) -join ' ' ) , # мл. / ст. и так далее [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] $Suffix <# , # г-н и так далее - обращение [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] $Title #> , # пол [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] [Alias("sex")] $Gender , # дата рождения [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.DateTime] $Birthday , # родной язык [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] $Language , # категории [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] $Categories , # наименование компании [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] [Alias("company")] $CompanyName , # отдел [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] $Department , # должность [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] [Alias("title")] $JobTitle , # профессия [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] $Profession , # ФИО заместителя [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] [Alias("assistantCn")] $AssistantName , # телефон заместителя [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] $AssistantTelephoneNumber , # ФИО руководителя [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] [Alias("managerCn")] $ManagerName , # адрес - город [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] [Alias("l")] $BusinessAddressCity , # адрес - область [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] [Alias("o")] $BusinessAddressState , # адрес - страна [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] [Alias("co")] $BusinessAddressCountry , # адрес - индекс [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] [Alias("postalCode")] $BusinessAddressPostalCode , # адрес - улица и номер дома [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] [Alias("streetAddress")] $BusinessAddressStreet , # адрес - номер абонентского ящика [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] $BusinessAddressPostOfficeBox , # адрес - номер кабинета [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] [Alias("room")] $OfficeLocation , # факс рабочий [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] [Alias("facsimileTelephoneNumber")] $BusinessFaxNumber , # сайт рабочий [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] [Alias("wWWHomePage")] $BusinessHomePage , # телефон рабочий [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] [Alias("telephoneNumber")] $BusinessTelephoneNumber , # телефон мобильный [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] [Alias("mobile")] $MobileTelephoneNumber , # адрес электронной почты [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] [Alias("mail")] $Email1Address , <# # наименование контакта в списке контактов [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] $Email1DisplayName = $Subject , #> # IM адрес [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] $IMAddress = $Email1Address , # адрес, предоставляющий сведения о занятости [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] $InternetFreeBusyAddress , # передавать домены далее по конвейеру или нет [switch] $PassThru , # перезаписывать ли реквизиты существующих ящиков [switch] $Force ) begin { $Outlook = New-Object -ComObject Outlook.Application; $Contacts = $Outlook.GetNamespace('MAPI').GetDefaultFolder( [Microsoft.Office.Interop.Outlook.OlDefaultFolders]::olFolderContacts ).Items; } process { $Params = @{}; $GetContactParams = (Get-Command Get-Contact).Parameters; foreach ( $param in $PSBoundParameters.Keys ) { if ( $GetContactParams.ContainsKey($param) ) { $Params.$param = $PSBoundParameters.$param; }; }; $Contact = Get-Contact @Params; if ( $Contact -and -not $Force ) { Write-Error "Контакт $($Contact.Subject) существует. Для его перезаписи используйте ключ -Force."; } else { if ( -not $Contact ) { $Contact = $Contacts.Add( 2 ); }; $Contact ` | Set-Contact @PSBoundParameters ` | Out-Null ` ; if ( $PassThru ) { return $Contact; } }; } } function Set-Contact { <# .Component Outlook.Application .Synopsis Редактируем реквизиты контакта. .Description Редактируем реквизиты контакта. .Example Get-Contact -Filter "[Subject]='Бетке Сергей Сергеевич'" ` | Set-Contact -Email1Address 'ivan.ivanov@domain.net' ` ; #> [CmdletBinding( SupportsShouldProcess=$true , ConfirmImpact="Medium" )] param ( # Объект контакта, полученный через Get-Contact [Parameter( Mandatory=$false , ValueFromPipeline=$true )] [System.__ComObject] [Alias("Contact")] $InputObject , # Параметр, используется по сути только для определения переданного по конвейеру типа (потому как тип .net не определить в этом случае) [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true )] $MAPIOBJECT , # Фамилия [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] [ValidateNotNullOrEmpty()] [Alias("sn")] [Alias("SecondName")] $LastName , # Имя [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] [ValidateNotNullOrEmpty()] [Alias("givenName")] $FirstName , # Отчество [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] $MiddleName , # Инициалы [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] $Initials , # логин (он же - lname для почты и так далее) [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] [Alias("mailNickname")] $NickName , # полное наименование контакта (используем ФИО) [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] [Alias("cn")] $Subject = ( ( $LastName, $FirstName, $MiddleName | ? { $_ } ) -join ' ' ) , # мл. / ст. и так далее [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] $Suffix <# , # г-н и так далее - обращение [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] $Title #> , # пол [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] [Alias("sex")] $Gender , # дата рождения [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.DateTime] $Birthday , # родной язык [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] $Language , # категории [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] $Categories , # наименование компании [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] [Alias("company")] $CompanyName , # отдел [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] $Department , # должность [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] [Alias("title")] $JobTitle , # профессия [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] $Profession , # ФИО заместителя [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] [Alias("assistantCn")] $AssistantName , # телефон заместителя [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] $AssistantTelephoneNumber , # ФИО руководителя [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] [Alias("managerCn")] $ManagerName , # адрес - город [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] [Alias("l")] $BusinessAddressCity , # адрес - область [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] [Alias("o")] $BusinessAddressState , # адрес - страна [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] [Alias("co")] $BusinessAddressCountry , # адрес - индекс [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] [Alias("postalCode")] $BusinessAddressPostalCode , # адрес - улица и номер дома [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] [Alias("streetAddress")] $BusinessAddressStreet , # адрес - номер абонентского ящика [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] $BusinessAddressPostOfficeBox , # адрес - номер кабинета [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] [Alias("room")] $OfficeLocation , # факс рабочий [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] [Alias("facsimileTelephoneNumber")] $BusinessFaxNumber , # сайт рабочий [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] [Alias("wWWHomePage")] $BusinessHomePage , # телефон рабочий [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] [Alias("telephoneNumber")] $BusinessTelephoneNumber , # телефон мобильный [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] [Alias("mobile")] $MobileTelephoneNumber , # адрес электронной почты [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] [Alias("mail")] $Email1Address , <# # наименование контакта в списке контактов [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] $Email1DisplayName = $Subject , #> # IM адрес [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] $IMAddress = $Email1Address , # адрес, предоставляющий сведения о занятости [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] $InternetFreeBusyAddress , [switch] $PassThru , # создание контакта в случае его отсутствия [switch] $Force ) begin { $Outlook = New-Object -ComObject Outlook.Application; $Contacts = $Outlook.GetNamespace('MAPI').GetDefaultFolder( [Microsoft.Office.Interop.Outlook.OlDefaultFolders]::olFolderContacts ).Items; } process { if ( -not ( $InputObject -and $InputObject.MAPIOBJECT ) ) { $Params = @{}; $GetContactParams = (Get-Command Get-Contact).Parameters; foreach ( $param in $PSBoundParameters.Keys ) { if ( $GetContactParams.ContainsKey($param) ) { $Params.$param = $PSBoundParameters.$param; }; }; $InputObject = Get-Contact @Params; }; if ( -not ( $InputObject ) ) { if ( -not $Force ) { Write-Error "Контакт $($Contact.Subject) не существует. Для его создания используйте ключ -Force."; } else { if ( $PSCmdlet.ShouldProcess( $LastName, "Создание контакта" ) ) { Write-Verbose "Контакт для редактирования не передан явно и не обнаружен автоматически, создаём контакт."; $InputObject = $Contacts.Add( 2 ); }; }; } if ( $InputObject ) { if ( $PSCmdlet.ShouldProcess( $InputObject.Subject, "Изменение реквизитов" ) ) { Write-Verbose "Изменяем реквизиты контакта $($InputObject.Subject)."; $Params = (Get-Command Set-Contact).Parameters; $Params.Keys ` | ? { $Params.$_.ParameterSets.ContainsKey('contactProperties') } ` | ? { $PSBoundParameters.$_ } ` | % { $InputObject.$_ = $PSBoundParameters.$_; } ` ; $InputObject.Save(); $InputObject.Subject = ( $InputObject.LastName, $InputObject.FirstName, $InputObject.MiddleName ` | ? { $_ } ) -join ' '; if ( $Email1Address ) { $InputObject.Email1DisplayName = $InputObject.Subject; }; $InputObject.Save(); $InputObject.Close(0); }; }; if ( $PassThru ) { $input }; } } function Remove-Contact { <# .Component Outlook.Application .Synopsis Удаляем контакт .Description Удаляем контакт .Example Get-Content ` -path $usersCsvFile ` | ConvertFrom-Csv ` -UseCulture ` | Get-Contact ` | Remove-Contact ` ; #> [CmdletBinding( SupportsShouldProcess=$true , ConfirmImpact="High" )] param ( # Объект контакта, полученный через Get-Contact [Parameter( Mandatory=$true , ValueFromPipeline=$true )] [System.__ComObject] [Alias("Contact")] $InputObject ) process { if ( $PSCmdlet.ShouldProcess( $InputObject.Subject, "Удаление контакта" ) ) { Write-Verbose "Удаляем контакт $($InputObject.Subject)."; $InputObject.Delete(); }; } } Export-ModuleMember ` Get-Contact ` , New-Contact ` , Set-Contact ` , Remove-Contact ` ;
Благодаря приведённому выше модулю Вы теперь можете и запрашивать и обрабатывать объекты контактов Outlook в стиле PoSh:
Get-OutlookContact ` -Filter '[LastName]="Бетке" AND [FirstName]="Сергей"' ` | Set-OutlookContact ` -CompanyName 'IT-Сервис, ООО ` -PassThru ` | Select-Object Subject, EMail1DisplayName, EMail1Address ` | Out-GridView ` ;
Так ведь явно приятнее в PowerShell, чем писать груду dotNet кода?
Из тонкостей обращаю внимание на применение атрибутов параметров ValueFromPipelineByPropertyName=$true
. Приведу небольшую цитату из приведённого выше кода модуля:
# Фамилия [Parameter( Mandatory=$false , ValueFromPipelineByPropertyName=$true , ParameterSetName="ContactProperties" )] [System.String] [ValidateNotNullOrEmpty()] [Alias("sn")] [Alias("SecondName")] $LastName
Мы описываем параметр для командлетов New-Contact
, Set-Contact
как необязательный, при этом сообщаем, что его значением может быть установлено из одноимённого (с учётом псевдонимов!) свойства объекта, поступившего по конвейеру (pipeline) нашему командлету. Идентификатор параметра в точности соответствует идентификатору свойства Фамилия объекта "Контакт" MS Outlook. А псевдоним совпадает с идентификатором соответствующего свойства объектов User и Contact из AD. Такой подход позволяет передать по конвейеру нашим командлетам выход Get-ADUser
без предварительной обработки, и при этом параметр $LastName
получит значение реквизита sn
объекта AD. Другими словами, сопоставление реквизитов объекта Контакт MS Outlook и AD User мы осуществили в описании параметра командлета!
А теперь цитата кода, осуществляющего непосредственно изменение свойств объект Контакт:
$Params = (Get-Command Set-Contact).Parameters; $Params.Keys ` | ? { $Params.$_.ParameterSets.ContainsKey('contactProperties') } ` | ? { $PSBoundParameters.$_ } ` | % { $InputObject.$_ = $PSBoundParameters.$_; } ` ; $InputObject.Save();
Этим кодом мы изменяем все те и только те свойства, значения которых либо явно определены при применении командлеты, либо определены по реквизитам поступившего по конвейеру объекта! Суть кода в следующем: мы получаем коллекцию описаний параметров командлеты Set-Contact. Зачем выбираем те параметры, которые отнесены к набору параметров ‘contactProperties’ (в данном случае набор параметров использовал исключительно для группировки параметров, соответствующих свойствам объекта Контакт, не более). После чего проверяем – установлено ли значение параметра. И только если оно установлено – меняем соответствующее свойства объекта Контакт.
Такая вот обёртка…
В ближайшее время планирую добавить командлеты ConvertTo-OutlookContact, ConvertFrom-OutlookContact. Суть последней – в преобразовании объекта Контакт MS Outlook в объекта класса PSObject с набором свойств, соответствующим именовании аналогичных свойств в AD. В этом случае мы сможем выполнить и обратную процедуру – из коллекции контактов Outlook создать объекты Contact в AD.
В общем – буду благодарен Вам за любые комментарии и предложения. С уважением приму комиты в проект на github.
RSS комментарии
Обратная ссылка