Статья размещена автором Бетке Сергей Сергеевич

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.

Опубликовать комментарий

XHTML: Вы можете использовать следующие HTML теги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Tags Связь с комментариями статьи:
RSS комментарии
Обратная ссылка