Exchange 200x Store  Sinks

Store Event Sinks gibt es erst seit Exchange 2000 und sind auch bei Exchange 2007 weiterhin nutzbar und erforderlich, wenn man "synchron" arbeiten muss. Für asynchrone Verarbeitungen können auch Webservices Notification.

Ehe Sie über "Store Eventsinks" nachdenken, sollten Sie wissen, dass hier eine sehr gute Code Qualität gewährleistet sein muss. Schließlich startet der Exchange Store selbst (STORE.EXE) dann ihren Code für bestimmte Ereignisse. Man kann mit solchen Sinks nahezu alles in Exchange verändern und natürlich auch Exchange an die Wand drücken.

Storesink Grundlagen

Normalweise muss man seinen Code erst mal als "COM"-DLL bauen und auf dem Server installieren. Dieser Code muss die folgenden Methoden unterstützen:

Die "OnSync"-Funktionen laufen synchron ab, d.h. die Weiterverarbeitung dieses Objekts wird solange verzögert, bis ihr eigener Code beendet ist. Die beiden ersten Events starten ihr Skript, aber lassen die Speicherung der Änderung zu. Wer also nur "mitschneiden" will, was im Store gelöscht wird, der kann mit "OnDelete" arbeiten. Wer aber Löschungen durch den User verhindern oder Speicherungen modifizieren will, sollte mit OnSyncDelete und OnSyncSave implementieren. Bei NetatWork haben wir schon einige Sinks entwickelt, die z.B. Verhindern, dass ein PDA mit ActiveSync die Messageclass von einem benutzerdefinierten Formular auf das Standardformular zurück ändert. (OnSyncSave). Mti einem "OnSave"-Event könnte man z.B.: dafür sorgen, dass Änderungen in Kontakten als Kopie in eine Datenbank übertragen werden oder ins Archiv kopiert werden. Der Einsatzbereich von StoreSinks ist sehr breit.

Nachdem Sie ihren Code also entwickelt und installiert haben, müssen Sie Exchange noch mitteilen, dass er diesen Code ausführen soll. Auch hierzu gibt es ein VBScript von Microsoft, welchem man einige Parameter und Filter übergeben muss:

Es ist immer eine gute Idee, nur die Datenquellen anzuzapfen, die auch erforderlich sind. Wenn sie nur wenige Ordner bearbeiten wollen, dann sollten Sie besser diese Ordner einzeln "registrieren", statt mit einer globalen Registrierung alle Mails an ihren Code zu geben und dort dann erst die unerwünschten zu verwerfen. Storesinks können auch schnell die Exchange Performance beeinträchtigen.

Bedenken Sie auch immer, dass Exchange "Multithreaded" ist und ihr Code daher auch parallele Aufrufe korrekt verarbeiten muss und es keine Sperren gibt. Gerade bei "OnSync"-Aufrufen kann ihr Exchange Server dann sehr schnell "stehen".

Globale Store Event Sinks

Neben den Sinks, die Sie auf einzelne Ordner und Ordnerstrukturen anwenden können, gibt es auch die Option, einen globalen Sink auf dem Store selbst zu registrieren. An diesen Code müssen natürlich noch höhere Anforderungen gestellt werden, da er für sehr viele Aktionen aufgerufen werden kann. Der Einsatzbereich eines solchen globalen Sink kann sehr vielfältig sein. Denkbar sind z.B.:

Da stellt sich natürlich die Frage, ob so ein globaler Sink nicht die Performance des Servers allzu stark beeinflusst. Leider gibt es keine klare Antwort darauf, da vieles davon abhängt, wie intelligent der Sink geschrieben ist und was er tut. Er muss auf jeden Fall reentrant sein, damit mehrere Prozesse parallel ablaufen können. Zudem sollte er eben nicht allzu lange blockieren, da dies der Anwender sicher merken würde. Für eine Zusatzfunktion auf einem einzelnen Ordner gleich einen globalen Sink zu registrieren ist sicherlich überdimensioniert. Allerdings ist es auch nicht gerade der Performance zuträglich, wenn Sie viele einzelne gleichartige Sinks entwickeln und an den betreffenden Ordner binden. Hier ist demnach Testen angesagt.

Wenn Sie hingegen nur protokollieren wollen, wer einen öffentlichen Ordner löscht, dann könnte folgender Artikel interessant sein:

Eine Besonderheit bei Store Event Sinks ist die Einrichtung als globaler Sink. Wird der Sink auf die System Mailbox registriert, dann wird der Sink für "JEDE" Aktion auf dem Informationsspeicher dieser Mailbox zweimal ausgeführt:

Das muss man also als Entwickler auch berücksichtigen, damit der eigene Code nicht doppelt aktiv wird.

Obwohl Microsoft Support etwas anderes erzählt, kann man wohl sogar globale Sinks auf öffentliche Ordner einrichten. Verlassen würde ich mich darauf aber nicht, dass es mit jeder Version funktioniert.

Mustersink mit VBScript

Auch wenn man es "eigentlich" nicht tun sollte, so kann man tatsächlich auch mit VBScript einen Store Event Sink programmieren. Im TechNet Artikel "895239 How to register a store event sink using Regevent.vbs on Exchange" ist hierzu sogar eine Schritt für Schritt Anleitung. Man benötigt hierfür jedoch eine "Helper.DLL", die Microsoft bei Exchange 2000 mitliefert aber nicht registriert hat. Der Exchange Store startet dann eigentlich diese HelperDLL, die dann ihrerseits das VBScript aufruft. Entsprechend sind dann auch die Schritt zu tun:

Dies ist ein Beispiel für wenig Last. Eine Anwendung auf einen aktiven Store mit vielen Benutzern und vielen Systemen ist definitiv nicht ratsam.

Für diese Demonstration gibt es einen Infofilm unter dem Namen storesink.wmv (4MB)

Die hier verwendeten Beispiele und Skripte finden Sie hier als Archiv.
storesink-sample.zip

<SCRIPT LANGUAGE="VBScript">

public Sub ExStoreEvents_OnDelete(pEventInfo, bstrURLItem, lFlags)
	Dim fso
	Dim txtfile
	Set fso = CreateObject("Scripting.FileSystemObject")
	Set txtfile = fso.OpenTextFile("c:\msxfaq.samplesink\msxfaq.samplesink.log", 8, True)
	txtfile.WriteLine ("Object geloescht:" & bstrURLItem)
	txtfile.Close
End Sub

</SCRIPT>

Sie können das Skript nicht per CSCRIPT einfach aufrufen. CScript stört isch an den >Script> Tags.

regsvr32 C:\Programme\exchsrvr\bin\exodbesh.dll
regsvr32 C:\Programme\exchsrvr\bin\exodbprx.dll
cscript regevent.vbs add "ondelete" ExOleDB.ScriptEventSink.1
  "file://./backofficestorage/msxfaq.de/MBX/Administrator/Posteingang/msxfaqsamplesink.evt"
  -m deep -file "c:\msxfaq.samplesink\msxfaqsamplesink.vbs"

Achtung: Sinks können nicht auf "Gesendete Objekte" oder den "Postausgang" registriert werden
Siehe auch Q297274 PRB: Store Events Do Not Fire on the Outbox or Sent Item Folders

Anders als bei Storesinks, die als COM-Objekt eingebunden werden, wird das Skript in den fraglichen Ordner kopiert. Auch wenn es verborgen ist, kann damit theoretisch auch ein Anwender diesen Code sehen und sogar ändert, der dann vom Server ausgeführt wird. Spätestens hier sehen Sie dann, dass diese Beispielanwendung nicht produktiv gehen darf.

Der Sink wirkt dann auf den Posteingang. Genau diesen Sink können Sie mit folgender Zeile wieder entfernen.

cscript regevent.vbs delete 
  "file://./backofficestorage/msxfaq.de/MBX/Administrator/Posteingang/msxfaqsamplesink.evt"

Sink mit dem Exchange Explorer registrieren

Wem die letzte Kommandozeile zu kompliziert ist, kann auch mit dem Exchange Explorer (Ebenfalls im Exchange SDK) auch per grafischer Oberfläche einen Sink eintragen und entfernen.

Exchange Explorer

Danach startet ein Assistent, der Sie nacheinander alle Optionen abfragt:

Hintergründe und Debugging

Im Hintergrund wird das Skript als verborgende Nachricht in den entsprechenden Ordner kopiert. Der Anwender kann das Skript nicht sehen. Sollte das Skript aber sichtbar sein (weil ein Virenscanner z.B. beim Anlegen die Eigenschaften verhindert hat, dann wird es nicht gestartet. Diesen "Trick" nutzen viele andere Programme ebenfalls um Konfigurationsdaten zu verbergen. So speichert Outlook 2007 seine RSS-Feed Informationen. Sehen kann man diese Informationen z.B. mit MFCMAPI. oder dem Exchange Explorer oder Mistaya. Wenn Sie weitere Fehler haben, dann schauen Sie sich mal die folgende Seite an:

Event Type:       Error
Event Source:   EXOLEDB
Event Category:               Events 
Event ID:             116
Computer:         SRV01
Description:
Microsoft Exchange OLEDB was unable to initialize event system correctly.
Support for store event may have been disabled. HRESULT = 0x8000ffff. 
Event Type:       Error
Event Source:   EXOLEDB
Event Category:               Events 
Event ID:             116
Computer:         SRV01
Description:
Microsoft Exchange OLEDB was unable to initialize event system correctly.
Support for store event may have been disabled. HRESULT = 0x80004005. 

Auch im Windows Performance Counter System kann man die Aktivität der Sinks sehen

StoreSink Performance Counter

Weitere Links

Hier nur eine kleine Auswahl von Links. Die MSDN-Seite ist sicher die beste Quelle

Produkte, die Storesinks nutzen

Keywords: Storesink Sample VBScript Eventsink