Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   [решено] Exchange. Экспорт контактов (http://forum.oszone.net/showthread.php?t=305397)

rox33 14-09-2015 13:15 2552971

Exchange. Экспорт контактов
 
Уважаемые, добрый день!
Такая появилась проблема.
Необходимо выгружать контакты пользователей из Exchange в автоматическом режиме.
Нашел скрипт
Скрытый текст
Цитата:

## Get the Mailbox to Access from the 1st commandline argument

$MailboxName = $args[0]

## Load Managed API dll
Add-Type -Path "C:\Program Files\Microsoft\Exchange\Web Services\2.0\Microsoft.Exchange.WebServices.dll"

## Set Exchange Version
$ExchangeVersion = [Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010_SP2

## Create Exchange Service Object
$service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService($ExchangeVersion)

## Set Credentials to use two options are availible Option1 to use explict credentials or Option 2 use the Default (logged On) credentials

#Credentials Option 1 using UPN for the windows Account
$psCred = Get-Credential
$creds = New-Object System.Net.NetworkCredential($psCred.UserName.ToString(),$psCred.GetNetworkCredential().password.ToS tring())
$service.Credentials = $creds

#Credentials Option 2
#service.UseDefaultCredentials = $true

## Choose to ignore any SSL Warning issues caused by Self Signed Certificates

## Code From http://poshcode.org/624
## Create a compilation environment
$Provider=New-Object Microsoft.CSharp.CSharpCodeProvider
$Compiler=$Provider.CreateCompiler()
$Params=New-Object System.CodeDom.Compiler.CompilerParameters
$Params.GenerateExecutable=$False
$Params.GenerateInMemory=$True
$Params.IncludeDebugInformation=$False
$Params.ReferencedAssemblies.Add("System.DLL") | Out-Null

$TASource=@'
namespace Local.ToolkitExtensions.Net.CertificatePolicy{
public class TrustAll : System.Net.ICertificatePolicy {
public TrustAll() {
}
public bool CheckValidationResult(System.Net.ServicePoint sp,
System.Security.Cryptography.X509Certificates.X509Certificate cert,
System.Net.WebRequest req, int problem) {
return true;
}
}
}
'@
$TAResults=$Provider.CompileAssemblyFromSource($Params,$TASource)
$TAAssembly=$TAResults.CompiledAssembly

## We now create an instance of the TrustAll and attach it to the ServicePointManager
$TrustAll=$TAAssembly.CreateInstance("Local.ToolkitExtensions.Net.CertificatePolicy.TrustAll")
[System.Net.ServicePointManager]::CertificatePolicy=$TrustAll

## end code from http://poshcode.org/624

## Set the URL of the CAS (Client Access Server) to use two options are availbe to use Autodiscover to find the CAS URL or Hardcode the CAS to use

#CAS URL Option 1 Autodiscover
$service.AutodiscoverUrl($MailboxName,{$true})
"Using CAS Server : " + $Service.url

#CAS URL Option 2 Hardcoded

#$uri=[system.URI] "https://casservername/ews/exchange.asmx"
#$service.Url = $uri

## Optional section for Exchange Impersonation

#$service.ImpersonatedUserId = new-object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, $MailboxName)
$ExportCollection = @()
Write-Host "Process Contacts"
$folderid= new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Contacts,$MailboxName)
$Contacts = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$folderid)

$psPropset = new-object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties)
$PR_Gender = New-Object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(14925,[Microsoft.Exchange.WebServices.Data.MapiPropertyType]::Short)
$psPropset.Add($PR_Gender)

#Define ItemView to retrive just 1000 Items
$ivItemView = New-Object Microsoft.Exchange.WebServices.Data.ItemView(1000)
$fiItems = $null
do{
$fiItems = $service.FindItems($Contacts.Id,$ivItemView)
[Void]$service.LoadPropertiesForItems($fiItems,$psPropset)
foreach($Item in $fiItems.Items){
if($Item -is [Microsoft.Exchange.WebServices.Data.Contact]){
$expObj = "" | select DisplayName,GivenName,Surname,Gender,Email1DisplayName,Email1Type,Email1EmailAddress,BusinessPhone,M obilePhone,HomePhone,BusinessStreet,BusinessCity,BusinessState,HomeStreet,HomeCity,HomeState
$expObj.DisplayName = $Item.DisplayName
$expObj.GivenName = $Item.GivenName
$expObj.Surname = $Item.Surname
$expObj.Gender = ""
$Gender = $null
if($item.TryGetProperty($PR_Gender,[ref]$Gender)){
if($Gender -eq 2){
$expObj.Gender = "Male"
}
if($Gender -eq 1){
$expObj.Gender = "Female"
}
}
$BusinessPhone = $null
$MobilePhone = $null
$HomePhone = $null
if($Item.PhoneNumbers -ne $null){
if($Item.PhoneNumbers.TryGetValue([Microsoft.Exchange.WebServices.Data.PhoneNumberKey]::BusinessPhone,[ref]$BusinessPhone)){
$expObj.BusinessPhone = $BusinessPhone
}
if($Item.PhoneNumbers.TryGetValue([Microsoft.Exchange.WebServices.Data.PhoneNumberKey]::MobilePhone,[ref]$MobilePhone)){
$expObj.MobilePhone = $MobilePhone
}
if($Item.PhoneNumbers.TryGetValue([Microsoft.Exchange.WebServices.Data.PhoneNumberKey]::HomePhone,[ref]$HomePhone)){
$expObj.HomePhone = $HomePhone
}
}
if($Item.EmailAddresses.Contains([Microsoft.Exchange.WebServices.Data.EmailAddressKey]::EmailAddress1)){
$expObj.Email1DisplayName = $Item.EmailAddresses[[Microsoft.Exchange.WebServices.Data.EmailAddressKey]::EmailAddress1].Name
$expObj.Email1Type = $Item.EmailAddresses[[Microsoft.Exchange.WebServices.Data.EmailAddressKey]::EmailAddress1].RoutingType
$expObj.Email1EmailAddress = $Item.EmailAddresses[[Microsoft.Exchange.WebServices.Data.EmailAddressKey]::EmailAddress1].Address
}
$HomeAddress = $null
$BusinessAddress = $null
if($item.PhysicalAddresses -ne $null){
if($item.PhysicalAddresses.TryGetValue([Microsoft.Exchange.WebServices.Data.PhysicalAddressKey]::Home,[ref]$HomeAddress)){
$expObj.HomeStreet = $HomeAddress.Street
$expObj.HomeCity = $HomeAddress.City
$expObj.HomeState = $HomeAddress.State
}
if($item.PhysicalAddresses.TryGetValue([Microsoft.Exchange.WebServices.Data.PhysicalAddressKey]::Business,[ref]$BusinessAddress)){
$expObj.BusinessStreet = $BusinessAddress.Street
$expObj.BusinessCity = $BusinessAddress.City
$expObj.BusinessState = $BusinessAddress.State
}
}

$ExportCollection += $expObj
}
}
$ivItemView.Offset += $fiItems.Items.Count
}while($fiItems.MoreAvailable -eq $true)

$fnFileName = "c:\temp\" + $MailboxName + "-ContactsExport.csv"
$ExportCollection | Export-Csv -NoTypeInformation -Path $fnFileName
"Exported to " + $fnFileName

Скрипт работает, но нужно два усовершенствования:
1. Скрипт должен брать credential из txt файла в формате name.name@domain.ru;password
2. Скрипт выгружает только папку контакты. Как задать, чтобы выгружал все подпапки в контактах?
Специалисты, помогите, пожалуйста!

Kazun 14-09-2015 13:38 2552987

1. Скрипт должен брать credential из txt файла в формате name.name@domain.ru;password


Код:

$pl = Import-Csv password.txt -Delimiter ";" -Header "Login","Password"

#Credentials Option 1 using UPN for the windows Account
$creds = New-Object System.Net.NetworkCredential($pl.Login,$pl.Password)
$service.Credentials = $creds

2. Выгрузка не поддерживает русский язык, вместо символов кириллицы "???????".
Код:

$ExportCollection | Export-Csv -NoTypeInformation -Path $fnFileName
заменить на:
Код:

$ExportCollection | Export-Csv -NoTypeInformation -Path $fnFileName -Encoding UTF8

Как планируется запускать скрипт ? Правки выше, если есть только 1 пользователь в файле.

Kazun 14-09-2015 16:40 2553064

Изменить txt файл в формат:

Код:

MailboxName;UserName;Password
mailbox@contoso.com;mailbox@contoso.com;Pass

И уже в цикле передевать значения, скажем:

Код:

$creds = Import-Csv users.txt -Delimiter ";"

foreach ($cred in $creds)
{
        ## Create Exchange Service Object
        $service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService($ExchangeVersion)
       
        $creds = New-Object System.Net.NetworkCredential($cred.UserName,$cred.Password))
        $service.Credentials = $creds
        $service.AutodiscoverUrl($cred.MailboxName,{$true})

Как получить все папки с контактами в которых больше 0:

Код:

$coFolderView = New-Object Microsoft.Exchange.WebServices.Data.FolderView(1000)
$coFolderView.Traversal = "Deep"

$sf = New-Object Collections.Generic.List["Microsoft.Exchange.WebServices.Data.SearchFilter"]
$sf.Add((New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.FolderSchema]::FolderClass,"IPF.Contact")))
$sf.Add((New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsGreaterThan([Microsoft.Exchange.WebServices.Data.FolderSchema]::TotalCount,0)))

$sf = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+SearchFilterCollection([Microsoft.Exchange.WebServices.Data.LogicalOperator]::And, $sf.ToArray())

$service.FindFolders($Contacts.Id,$sf,$coFolderView)

Как получить элементы из них, код есть выше.

rox33 14-09-2015 17:56 2553098

Я извиняюсь, но всё же можете подсказать, как именно получить элементы из подпапок и выгрузить их в файл?
И как выгрузить данные с нескольких учётных записей (из users.txt) в разные файлы username.csv?

Kazun 15-09-2015 11:05 2553336

Формат users.txt:

Код:

MailboxName;UserName;Password
user1@domai.ru;user@domain.ru;MYPassw01e
user2@domai.ru;user@domain.ru;MYPassw01e
user3@domai.ru;user@domain.ru;MYPassw01e

Скрипт:

Код:

Add-Type -Path "C:\Program Files\Microsoft\Exchange\Web Services\2.0\Microsoft.Exchange.WebServices.dll"

## Set Exchange Version
$ExchangeVersion = [Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010_SP2

## Choose to ignore any SSL Warning issues caused by Self Signed Certificates
## Code From http://poshcode.org/624
## Create a compilation environment
$Provider=New-Object Microsoft.CSharp.CSharpCodeProvider
$Compiler=$Provider.CreateCompiler()
$Params=New-Object System.CodeDom.Compiler.CompilerParameters
$Params.GenerateExecutable=$False
$Params.GenerateInMemory=$True
$Params.IncludeDebugInformation=$False
$Params.ReferencedAssemblies.Add("System.DLL") | Out-Null

$TASource=@'
namespace Local.ToolkitExtensions.Net.CertificatePolicy{
public class TrustAll : System.Net.ICertificatePolicy {
public TrustAll() {
}
public bool CheckValidationResult(System.Net.ServicePoint sp,
System.Security.Cryptography.X509Certificates.X509Certificate cert,
System.Net.WebRequest req, int problem) {
return true;
}
}
}
'@
$TAResults=$Provider.CompileAssemblyFromSource($Params,$TASource)
$TAAssembly=$TAResults.CompiledAssembly

## We now create an instance of the TrustAll and attach it to the ServicePointManager
$TrustAll=$TAAssembly.CreateInstance("Local.ToolkitExtensions.Net.CertificatePolicy.TrustAll")
[System.Net.ServicePointManager]::CertificatePolicy=$TrustAll


$creds = Import-Csv users.txt -Delimiter ";"

foreach ($cred in $creds)
{
        ## Create Exchange Service Object
        $service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService($ExchangeVersion)
       
        $creds = New-Object System.Net.NetworkCredential($cred.UserName,$cred.Password))
        $service.Credentials = $creds
       
        $MailboxName = $cred.MailboxName
       
        $service.AutodiscoverUrl($MailboxName,{$true})
        "Using CAS Server : " + $Service.url
       
        $ExportCollection = @()
        $Folders = @()
       
        $folderid= new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Contacts,$MailboxName)
        $Contacts = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$folderid)
       
        $Folders += $Contacts.Id
       
       
        $coFolderView = New-Object Microsoft.Exchange.WebServices.Data.FolderView(1000)
        $coFolderView.Traversal = "Deep"

        $sf = New-Object Collections.Generic.List["Microsoft.Exchange.WebServices.Data.SearchFilter"]
        $sf.Add((New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.FolderSchema]::FolderClass,"IPF.Contact")))
        $sf.Add((New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsGreaterThan([Microsoft.Exchange.WebServices.Data.FolderSchema]::TotalCount,0)))

        $sf = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+SearchFilterCollection([Microsoft.Exchange.WebServices.Data.LogicalOperator]::And, $sf.ToArray())

        $service.FindFolders($Contacts.Id,$sf,$coFolderView) | Foreach {$Folders += $_.Id}

        $psPropset = new-object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties)
        $PR_Gender = New-Object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(14925,[Microsoft.Exchange.WebServices.Data.MapiPropertyType]::Short)
        $psPropset.Add($PR_Gender)
       
        foreach($folder in $folders)
        {
                #Define ItemView to retrive just 1000 Items
                $ivItemView = New-Object Microsoft.Exchange.WebServices.Data.ItemView(1000)
                $fiItems = $null
                do {
                        $fiItems = $service.FindItems($Folder,$ivItemView)
                        [Void]$service.LoadPropertiesForItems($fiItems,$psPropset)
                        foreach($Item in $fiItems.Items){
                        if($Item -is [Microsoft.Exchange.WebServices.Data.Contact]){
                        $expObj = "" | select DisplayName,GivenName,Surname,Gender,Email1DisplayName,Email1Type,Email1EmailAddress,BusinessPhone,M obilePhone,HomePhone,BusinessStreet,BusinessCity,BusinessState,HomeStreet,HomeCity,HomeState
                        $expObj.DisplayName = $Item.DisplayName
                        $expObj.GivenName = $Item.GivenName
                        $expObj.Surname = $Item.Surname
                        $expObj.Gender = ""
                        $Gender = $null
                        if($item.TryGetProperty($PR_Gender,[ref]$Gender)){
                                if($Gender -eq 2){
                                        $expObj.Gender = "Male"
                                }
                                if($Gender -eq 1){
                                        $expObj.Gender = "Female"
                                }
                        }
               
                        $BusinessPhone = $null
                        $MobilePhone = $null
                        $HomePhone = $null
                        if($Item.PhoneNumbers -ne $null){
                                if($Item.PhoneNumbers.TryGetValue([Microsoft.Exchange.WebServices.Data.PhoneNumberKey]::BusinessPhone,[ref]$BusinessPhone)){
                                        $expObj.BusinessPhone = $BusinessPhone
                                }
                                if($Item.PhoneNumbers.TryGetValue([Microsoft.Exchange.WebServices.Data.PhoneNumberKey]::MobilePhone,[ref]$MobilePhone)){
                                        $expObj.MobilePhone = $MobilePhone
                                }
                                if($Item.PhoneNumbers.TryGetValue([Microsoft.Exchange.WebServices.Data.PhoneNumberKey]::HomePhone,[ref]$HomePhone)){
                                        $expObj.HomePhone = $HomePhone
                                }
                        }
                        if($Item.EmailAddresses.Contains([Microsoft.Exchange.WebServices.Data.EmailAddressKey]::EmailAddress1)){
                                $expObj.Email1DisplayName = $Item.EmailAddresses[[Microsoft.Exchange.WebServices.Data.EmailAddressKey]::EmailAddress1].Name
                                $expObj.Email1Type = $Item.EmailAddresses[[Microsoft.Exchange.WebServices.Data.EmailAddressKey]::EmailAddress1].RoutingType
                                $expObj.Email1EmailAddress = $Item.EmailAddresses[[Microsoft.Exchange.WebServices.Data.EmailAddressKey]::EmailAddress1].Address
                        }
                       
                        $HomeAddress = $null
                        $BusinessAddress = $null
                        if($item.PhysicalAddresses -ne $null){
                                if($item.PhysicalAddresses.TryGetValue([Microsoft.Exchange.WebServices.Data.PhysicalAddressKey]::Home,[ref]$HomeAddress)){
                                        $expObj.HomeStreet = $HomeAddress.Street
                                        $expObj.HomeCity = $HomeAddress.City
                                        $expObj.HomeState = $HomeAddress.State
                                }
                                if($item.PhysicalAddresses.TryGetValue([Microsoft.Exchange.WebServices.Data.PhysicalAddressKey]::Business,[ref]$BusinessAddress)){
                                        $expObj.BusinessStreet = $BusinessAddress.Street
                                        $expObj.BusinessCity = $BusinessAddress.City
                                        $expObj.BusinessState = $BusinessAddress.State
                                }
                        }

                        $ExportCollection += $expObj
                        }
                        }
                        $ivItemView.Offset += $fiItems.Items.Count
                } while($fiItems.MoreAvailable -eq $true)
        }
       
        $fnFileName = "c:\temp\" + $MailboxName + "_" + (Get-Date).ToString("ddMMyyyyHHmmss") + "_" + "-ContactsExport.csv"
        $ExportCollection | Export-Csv -NoTypeInformation -Path $fnFileName -Encoding UTF8
        "Exported to " + $fnFileName
}


rox33 15-09-2015 12:24 2553374

Kazun,
Скрипт, похоже, перебирает все папки и выдаёт несколько тысяч ошибок.
Начинается с Select-object : Не удается найти позиционный параметр, принимающий аргумент "System.Object[]"
А потом лопатит все свойства (BusinessPhone и пр.) и на каждое выдаёт ошибку.
в результате выгрузка не происходит =\
Поможете?
Спасибо огромное!

Kazun 15-09-2015 13:00 2553391

1) Оставить только одного пользователя
2) В угадайку играть не буду, каждую строку выполняем отдельно и все ошибки сюда.

rox33 15-09-2015 13:52 2553419

1) Оставил 1го пользователя
2)
Скрытый текст
Process Contacts
Select-Object : Не удается найти позиционный параметр, принимающий аргумент "System.Object[]".
C:\soft\final_ps.ps1:95 знак:19
+ $expObj = "" | select DisplayName,GivenName,Surname,Gender,Email1DisplayName, ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Select-Object], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.SelectObjectCommand

Не удается найти свойство "DisplayName" для данного объекта. Убедитесь, что оно существует и его можно задать.
C:\soft\final_ps.ps1:96 знак:4
+ $expObj.DisplayName = $Item.DisplayName
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyNotFound

Не удается найти свойство "GivenName" для данного объекта. Убедитесь, что оно существует и его можно задать.
C:\soft\final_ps.ps1:97 знак:4
+ $expObj.GivenName = $Item.GivenName
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyNotFound

Не удается найти свойство "Surname" для данного объекта. Убедитесь, что оно существует и его можно задать.
C:\soft\final_ps.ps1:98 знак:4
+ $expObj.Surname = $Item.Surname
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyNotFound

И далее - остальное вставлять не стал, т.к. ругается на каждый параметр.
После перебора всех свойств выдаёт:
Скрытый текст
Export-Csv : Не удается привязать аргумент к параметру "InputObject", так как он имеет значение NULL.
C:\soft\final_ps.ps1:153 знак:22
+ $ExportCollection | Export-Csv -NoTypeInformation -Path $fnFileName -Encoding U ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Export-Csv], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ExportCsvCommand

крайняя ошибка выдаётся ещё несколько тысяч раз, после чего выгрузка записывается, но, в результате, пустая.
PS в последней версии скрипта в самом конце была лишняя }
Возможно где-то нет { ?

Kazun 15-09-2015 13:58 2553425

Убрать пробел в строке с Select в месте ,M obilePhone, должно ,MobilePhone,

rox33 15-09-2015 14:12 2553432

Цитата:

Цитата Kazun
Убрать пробел в строке с Select в месте ,M obilePhone, должно ,MobilePhone, »

Блин, в блокноте ошибку видно, а в редакторе PowerShell она автоматически "исправлена", при этом не работает =\
После исправления, в скрипте всё работает.


Время: 15:20.

Время: 15:20.
© OSzone.net 2001-