Fragensteller
Script zum auslesen einer ActiveSync Gruppe und erstellen von entsprechenden Kontakten

Allgemeine Diskussion
-
Hallo,
ich habe ein Script, welches mir alle meine Kontakte aus einer Gruppe ausliest und diese dann per ActiveSync, die ganzen Kontake hinzufügen lässt. Leider läuft dieses nicht gerade performant. Es dauert länger als 4 Stunden bis dieses einmal komplett durchlaufen wird. Und das obwohl es sich hier nur um ca. 350 Kontakte handelt.
Habt ihr hier irgendwelche Verbesserungen, um das Script schneller zu gestalten? Evtl. Abfragen an bestimmten Stellen etc.
Extrem lange braucht das Script beim durchlaufen der Kontakte an dieser Stelle:
immer nur Maximal 50 Elemete aus dem Kontakordner holen # maximale Anzahl die eine Itemsuche zurückliefern soll $ItemPageSize = 50 # wenn weniger als 50 Elemente vorhanden sind, dann wird die Anzahl # auf die Elemente im Kontakordner reduziert If($ContacsFolder.TotalCount -lt 50) { $ItemPageSize = $ContacsFolder.TotalCount } # Startpunkt der Itemsuche $ItemOffset = 0 # Schleife um Elemente aus dem Kontaktordner zu holen beginnen Do { # Den Item-View einrichten um einen beschränkte Anzahl an Items zu holen $itemView = New-Object Microsoft.Exchang
System: Exchange 2010 SP3
param([string]$Group="ActiveSync",[string]$FolderName="Kontakte",$AddContact=0,$LogPath="C:\log"); # # Parameters # -Group: Group to sync Contacts # -FolderName: FolderName displayed in Outlook # -GroupDelete: Group to delete Contacts # ################################### # Function to write Logfile ################################### function Write-Log ($Inhalt) { $DateNow = Get-Date -Format "dd.MM.yyyy HH:mm:ss" # Ermittelt das aktuelle Datum mit diesem Syntax 01.10.2013 10:00 $date = Get-Date -Format "yyyy-MM-dd" $Logfile = "$LogPath\$date.log" $FileExists = Test-Path $LogFile $FileInp = $DateNow + ' | ' + $Inhalt # Setzt die Zeile für unser Logfile zusammen If ($FileExists -eq $True){ # Wenn dir Datei existiert reinschreiben Add-Content $LogFile -value $FileInp # Zeile hinten an die vorhanden Einträge anhängen } else { New-Item $Logfile -type file # Wenn dir Datei nicht existiert anlegen Add-Content $LogFile -value $FileInp # und reinschreiben } } Import-Module ActiveDirectory add-pssnapin Microsoft.Exchange.Management.PowerShell.E2010 $EwsUrl = ([array](Get-WebServicesVirtualDirectory))[0].InternalURL.AbsoluteURI $ContactMapping=@{ "FirstName" = "GivenName"; "LastName" = "Surname"; "Company" = "CompanyName"; "Department" = "Department"; "Title" = "JobTitle"; "WindowsEmailAddress" = "Email:EmailAddress1"; "Phone" = "Phone:BusinessPhone"; "MobilePhone" = "Phone:MobilePhone"; "HomePhone" = "Phone:HomePhone"; "Fax" = "Phone:BusinessFax"; } # Alle Benutzer aus einer Gruppe auslesen - Auswahl des Namen $Mailboxes = Get-ADGroupMember $Group | select -ExpandProperty name foreach($Mailbox in $Mailboxes) { $UserMailbox = Get-Mailbox $Mailbox -ErrorAction if (!$UserMailbox) { #throw "Mailbox $($Mailbox) not found"; exit; } else { Write-Log("Mailboxsync: $Mailbox") } $EmailAddress = $UserMailbox.PrimarySMTPAddress # Load EWS Managed API [void][Reflection.Assembly]::LoadFile("C:\Program Files\Microsoft\Exchange\Web Services\1.2\Microsoft.Exchange.WebServices.dll"); $service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010_SP3) $service.UseDefaultCredentials = $true; $service.URL = New-Object Uri($EwsUrl); # Search for an existing copy of the Folder to store Org contacts $service.ImpersonatedUserId = New-Object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, $EmailAddress); $RootFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,[Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot) $RootFolder.Load() $service.ImpersonatedUserId = New-Object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, $EmailAddress); $FolderView = new-Object Microsoft.Exchange.WebServices.Data.FolderView(1000) $ContactsFolderSearch = $RootFolder.FindFolders($FolderView) | Where {$_.DisplayName -eq $FolderName} if ($ContactsFolderSearch) { # Empty if found $service.ImpersonatedUserId = New-Object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, $EmailAddress); $ContactsFolder = [Microsoft.Exchange.WebServices.Data.ContactsFolder]::Bind($service,$ContactsFolderSearch.Id); } # Add contacts $Users = get-user -Filter {WindowsEmailAddress -ne $null -and (MobilePhone -ne $null -or Phone -ne $null) -and WindowsEmailAddress -ne $EmailAddress} $Users = $Users | select DisplayName,FirstName,LastName,Title,Company,Department,WindowsEmailAddress,Phone,MobilePhone,HomePhone,Fax foreach ($ContactItem in $Users) { $service.ImpersonatedUserId = New-Object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, $EmailAddress); $ExchangeContact = New-Object Microsoft.Exchange.WebServices.Data.Contact($service); if ($ContactItem.FirstName -and $ContactItem.LastName) { $ExchangeContact.NickName = $ContactItem.FirstName + " " + $ContactItem.LastName; } elseif ($ContactItem.FirstName -and !$ContactItem.LastName) { $ExchangeContact.NickName = $ContactItem.FirstName; } elseif (!$ContactItem.FirstName -and $ContactItem.LastName) { $ExchangeContact.NickName = $ContactItem.LastName; } elseif (!$ContactItem.FirstName -and !$ContactItem.LastName) { $ExchangeContact.NickName = $ContactItem.DisplayName; $ContactItem.FirstName = $ContactItem.DisplayName; } $ExchangeContact.DisplayName = $ExchangeContact.NickName; $ExchangeContact.FileAs = $ExchangeContact.NickName; $ExchangeContact.CompanyName = $ContactItem.Company # This uses the Contact Mapping above to save coding each and every field, one by one. Instead we look for a mapping and perform an action on # what maps across. As some methods need more "code" a fake multi-dimensional array (seperated by :'s) is used where needed. foreach ($Key in $ContactMapping.Keys) { # Only do something if the key exists if ($ContactItem.$Key) { # Will this call a more complicated mapping? if ($ContactMapping[$Key] -like "*:*") { # Make an array using the : to split items. $MappingArray = $ContactMapping[$Key].Split(":") # Do action switch ($MappingArray[0]) { "Email" { $ExchangeContact.EmailAddresses[[Microsoft.Exchange.WebServices.Data.EmailAddressKey]::($MappingArray[1])] = $ContactItem.$Key.ToString(); } "Phone" { $ExchangeContact.PhoneNumbers[[Microsoft.Exchange.WebServices.Data.PhoneNumberKey]::($MappingArray[1])] = $ContactItem.$Key; } } } else { $ExchangeContact.($ContactMapping[$Key]) = $ContactItem.$Key; } } } $ContacsFolder = [Microsoft.Exchange.WebServices.Data.ContactsFolder]::Bind($Service,[Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Contacts,(New-Object -TypeName 'Microsoft.Exchange.WebServices.Data.PropertySet' -ArgumentList ([Microsoft.Exchange.WebServices.Data.BasePropertySet]::IdOnly),([Microsoft.Exchange.WebServices.Data.FolderSchema]::TotalCount))) # immer nur Maximal 50 Elemete aus dem Kontakordner holen # maximale Anzahl die eine Itemsuche zurückliefern soll $ItemPageSize = 50 # wenn weniger als 50 Elemente vorhanden sind, dann wird die Anzahl # auf die Elemente im Kontakordner reduziert If($ContacsFolder.TotalCount -lt 50) { $ItemPageSize = $ContacsFolder.TotalCount } # Startpunkt der Itemsuche $ItemOffset = 0 # Schleife um Elemente aus dem Kontaktordner zu holen beginnen Do { # Den Item-View einrichten um einen beschränkte Anzahl an Items zu holen $itemView = New-Object Microsoft.Exchange.WebServices.Data.ItemView($ItemPageSize,$ItemOffset,[Microsoft.Exchange.WebServices.Data.OffsetBasePoint]::Beginning) # Die ItemView Suche mit Shallow, sucht alle nicht gelöschten Items $itemView.Traversal = [Microsoft.Exchange.WebServices.Data.ItemTraversal]::Shallow # um die zurückgelieferte Datenmenge zu reduzieren, fordern wir in dem ItemView nur den Vornamen, Nachnamen und die 3 E-mail felder an $itemView.PropertySet = new-object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.ContactSchema]::GivenName, [Microsoft.Exchange.WebServices.Data.ContactSchema]::Surname, [Microsoft.Exchange.WebServices.Data.ContactSchema]::EmailAddress1, [Microsoft.Exchange.WebServices.Data.ContactSchema]::EmailAddress2, [Microsoft.Exchange.WebServices.Data.ContactSchema]::EmailAddress3, [Microsoft.Exchange.WebServices.Data.ContactSchema]::CompanyName, [Microsoft.Exchange.WebServices.Data.ContactSchema]::BusinessPhone) # Elemente mit hilfe des itemViews in dem Postfach suchen lassen $FindItems = $service.FindItems([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Contacts,$itemView) # jedes Item gefundene Item Durchlaufen ForEach ($Item in $FindItems.Items) { # Der kontakt Ordner kann auch Elemente enthalten die keine Kontakt sind (z.B. Verteiler-Listen)! # Wir nutzen hier nur Kontakt Elemente! If ($Item -is [Microsoft.Exchange.WebServices.Data.Contact]) { # Geprüft wird auf Vorname, Nachname und Firmenname if ((($ContactItem.FirstName -eq $Item.SurName) -AND ($ContactItem.LastName -eq $Item.GivenName) -AND ($ContactItem.Company -eq $item.CompanyName)) -OR (($ContactItem.FirstName -eq $Item.GivenName) -AND ($ContactItem.LastName -eq $Item.SurName) -AND ($ContactItem.Company -eq $item.CompanyName))) { $DelItem = $Item #$DelItem.Surname, $DelItem.GivenName <#$DelItem.PhoneNumbers[[Microsoft.Exchange.WebServices.Data.PhoneNumberKey]::BusinessPhone]#> [void]$DelItem.Delete([Microsoft.Exchange.WebServices.Data.DeleteMode]::HardDelete) } } } # Berechnen der des Offsets für die nächste suchschleife $ItemOffset += $ItemPageSize # wenn noch restliche Elemente im Kontaktordner vorhanden sind. # wird die Schleife wieder bei DO angefangen } While ($FindItems.MoreAvailable) # Save the contact $ExchangeContact.Save($ContactsFolder.Id); # Provide output that can be used on the pipeline #$ExchangeContact.Surname, $ExchangeContact.GivenName, $ExchangeContact.EmailAddresses[[Microsoft.Exchange.WebServices.Data.EmailAddressKey]::EmailAddress1] } }
- Bearbeitet Chris19141 Dienstag, 22. Januar 2019 11:58
- Typ geändert Denniver ReiningMVP, Moderator Mittwoch, 6. Februar 2019 11:47 .....