In einem unserem Microsoft System Center Service Manager (SCSM) Projekt gab es die Anforderung, mit dem SCSM Exchange Connector Postfächer auf einem Exchange 2010 so zu verarbeiten, dass Incidents im SCSM erstellt und mit den Antworten der Kunden aktualisiert werden. Dieser Beitrag zeigt, wie man mit Hilfe eines PowerShell-Scripts diese Anforderung erfüllt.


Die Anforderungen ist prinzipiell nichts Besonderes, jedoch sollte zusätzlich mittels Orchestrator eine Erweiterung implementiert werden, wodurch auf den Incidents Runbook-Activities hinterlegt wurden. Beim Testen stellten wir dann fest, dass die Verarbeitung der Mails mittels SCSM Exchange Connector (Version 3.0 aus Oktober 2013) bei allen Incidents, die mit einer Runbook-Activitiy aktualisiert waren, nicht mehr funktionierte. Die Mails blieben gelesen in den Postfächern liegen. Im Eventlog des SCSM fand sich folgender Fehler:

Exchange Connector: Unable to process mail item. Subject=“[IR415] – Test extern“, Error Message=The key value of an object cannot be changed.

Leider ist das Logging des SCSM Exchange Connector nicht optimal  umgesetzt. Alle Events werden als Information rausgeschrieben und die Meldung ist nicht sehr aussagekräftig. Dadurch hat es auch eine Weile gedauert, bis wir den Fehler gefunden hatten. Eine Recherche bei Google und intensive Tests haben uns dann auf die Lösung gebracht.

Wir haben das Problem umgangen, indem wir die Erweiterung so umgesetzt haben, dass wir ohne Runbook-Activitiy auskommen.
Wir können nicht sagen, ob das Problem mit der aktuellen Version des SCSM Exchange Connector aus Juni 2014 immer noch besteht, da wir diese noch nicht im Einsatz haben.
Wir haben uns dann überlegt, wie wir Fälle, in denen der SCSM Exchange Connector nicht korrekt arbeitet, überwachen könnten. Dabei ist ein PowerShell-Script entstanden, welches per EWS (Exchange Web Services) die an SCSM angebundenen Postfächer auf Mails prüft, welche länger als 15 Minuten im Posteingang liegen. Da der SCSM Exchange Connector alle 5 Minuten läuft und Mails, welche korrekt verarbeitet wurden, aus dem Posteingang verschiebt, ist diese Prüfung valide. Die zu prüfenden Postfächer werden durch das Script aus dem SCSM ausgelesen. Werden Mails gefunden, wird ein Eventlog-Eintrag erzeugt, welchen wir mit SOM abfangen und uns per Mail alarmieren lassen.
Hier nun das Skript:

[code lang=“powershell“]

<#
.SYNOPSIS
check for mails in SCSM-mailboxes on exchange server
.DESCRIPTION
Use this script to check SCSM-mailboxes for stucked messages if processing of mails failed.
.PARAMETER $credential
optional, pass network credential with get-credential
.NOTES
Author: Andreas, Eric and Thomas, Data One GmbH
Date: 2015-02-28
LastEdit: 2015-02-28
Changelog:
2015-02-28
– initial version
.Link
Script: http://doitcloudy.blogspot.de/2015/02/powershell-uberwachung-von-scsm.html
#>
param ([System.Management.Automation.PSCredential] $credential) #pass credentials
#specify the delay in minutes
$threshold = (get-date).AddMinutes(-15)
[Reflection.Assembly]::LoadFrom(„C:Program FilesMicrosoft System Center 2012 R2Service ManagerMicrosoft.Exchange.WebServices.dll“)
Import-Module SMLets
#get the mailboxes from SCSM, special filter to exclude mailboxes with „SCSM“ in displayname
$connectors = Get-SCSMObject -Class (Get-SCSMClass -Name Microsoft.SystemCenter.Connector) | ?{$_.DataProviderDisplayName -eq „Exchange Connector“ -AND $_.DisplayName -notlike „*(SCSM)*“ -AND $_.Enabled} | select ImpersonationEmailAddress
$exService =  New-Object Microsoft.Exchange.WebServices.Data.ExchangeService -ArgumentList([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010_SP1)
#use credential, which was passed to the script
if ($credential) {
    $exService.Credentials = $credential.GetNetworkCredential()
}
#if no credential was passed to the script, use the credential from logged on user
else {
    $exService.UseDefaultCredentials = $true
}
function GetInboxMails([string] $emailAddress) {
    $exService.AutodiscoverUrl($emailAddress, {$true})
    $mailbox = New-Object Microsoft.Exchange.WebServices.Data.Mailbox($emailAddress)
    $folderId = New-Object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox, $mailbox)
    $inbox = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($exService,$folderid)
    $itemView =  New-Object Microsoft.Exchange.WebServices.Data.ItemView(250)
    $propertySet= new-object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::IdOnly)
    $propertySet.Add([Microsoft.Exchange.WebServices.Data.ItemSchema]::Size)
    $propertySet.Add([Microsoft.Exchange.WebServices.Data.ItemSchema]::DateTimeReceived)
    $propertySet.Add([Microsoft.Exchange.WebServices.Data.ItemSchema]::DateTimeCreated)
    $itemView.PropertySet = $propertySet
    $searchFilter = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsLessThan([Microsoft.Exchange.WebServices.Data.ItemSchema]::DateTimeReceived,$threshold)
    $mails = $exService.FindItems($inbox.Id,$searchFilter,$itemView)
    If ($mails.TotalCount -ne „0“) {
        $totalCount = $mails.TotalCount
        $Address = $mailbox.address
        #write event into the application log
        $EventLog = New-Object System.Diagnostics.EventLog(„Application“)
        $EventLog.Source = „SCSMMailCheck“
        $EventLog.MachineName = „.“
     $EventLog.WriteEntry(„There are $TotalCount e-mails older than 15 minutes in Inbox folder of mailbox $Address. Please review manually.“, „Error“, 75);
    }
}
#loop through each mailbox and check for mails
Foreach ($Connector in $Connectors) {
    GetInboxMails($Connector.ImpersonationEmailAddress)
}

[/code]

 

Danke an die Kollegen Eric und Thomas, die bei der Erstellung und Implementierung des Scriptes unterstützt haben.

 

Weiteres