none
Script zum auslesen einer ActiveSync Gruppe und erstellen von entsprechenden Kontakten RRS feed

  • 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]         
            
        }
    }



    Dienstag, 22. Januar 2019 09:02