PDA

Показать полную графическую версию : [решено] Exchange. Экспорт контактов


rox33
14-09-2015, 13:15
Уважаемые, добрый день!
Такая появилась проблема.
Необходимо выгружать контакты пользователей из 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
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
Изменить 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
Я извиняюсь, но всё же можете подсказать, как именно получить элементы из подпапок и выгрузить их в файл?
И как выгрузить данные с нескольких учётных записей (из users.txt) в разные файлы username.csv?

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

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

rox33
15-09-2015, 13:52
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
Убрать пробел в строке с Select в месте ,M obilePhone, должно ,MobilePhone,

rox33
15-09-2015, 14:12
Убрать пробел в строке с Select в месте ,M obilePhone, должно ,MobilePhone, »
Блин, в блокноте ошибку видно, а в редакторе PowerShell она автоматически "исправлена", при этом не работает =\
После исправления, в скрипте всё работает.




© OSzone.net 2001-2012