Der Lifecycle beschreibt den vollständigen Lebenszyklus eines Add-ins, von der Entdeckung über die Aktivierung bis zur Deaktivierung. Ziel dieser Seite ist es, Add-in-Entwicklern das Zusammenspiel der vier Phasen nachvollziehbar zu machen, damit sie verstehen, wann welcher Teil ihres Codes ausgeführt wird und wie sie Probleme bei der Aktivierung diagnostizieren können.
Im Unterschied zur Architektur-Seite, die das Modell abstrakt beschreibt, zeigt diese Seite den konkreten Ablauf mit Log-Ausgaben und Sequenzen. Der Vorteil besteht darin, dass ein Entwickler beim Debugging sofort erkennen kann, in welcher Phase sich sein Add-in befindet und was als Nächstes passieren müsste.
Zurück zur Übersicht.
Phase 1: SCAN Phase 2: RESOLVE Phase 3: REGISTER Phase 4: ACTIVATE
───────────────── ───────────────── ───────────────────── ──────────────────
Plugin-Verzeichnisse Abhängigkeitsgraph Lazy-Command-Stubs DLL laden
↓ aufbauen Menüpunkte GetAbiInfo
plugin.json lesen ↓ Toolbar-Buttons CreatePlugin
↓ Topologisch sortieren Sidebar-Views ↓
NLS-Dateien laden ↓ Keybindings IPlugin.Activate
↓ Engine-Version Konfiguration ↓
Manifest validieren prüfen ↓ Stubs entfernen
↓ ↓ UI steht vollständig Echte Handler
psDiscovered psResolved registrieren
↓
psActive
┌──── Kein Code geladen ────┐ ┌── UI vollständig ──┐ ┌── DLL aktiv ──┐
Der Host durchsucht zwei Verzeichnisse nach plugin.json-Dateien:
| Scope | Pfad | Zweck |
| Machine | <exe>/plugins/ | Vom Administrator gebundelte Add-ins (MSI/GPO) |
| User | ~/.wvdsx/extensions/ | Vom Benutzer installierte Add-ins (Roaming-Profile-kompatibel) |
Jedes Unterverzeichnis, das eine plugin.json enthält, wird als Kandidat behandelt. Der Host lädt die NLS-Dateien (package.nls.json + sprachspezifische Variante) und ersetzt %platzhalter%-Tokens im Manifest durch die übersetzten Texte.
Danach wird das Manifest validiert. Pflichtfelder wie id, name, version und main müssen vorhanden sein. Fehlende Felder führen dazu, dass das Add-in übersprungen wird — der Host zeigt eine Warnung, bricht aber nicht ab.
Typische Log-Ausgabe:
[INFO] Plugin scanning 2 search path(s) [DEBUG] Plugin discovered: "wvds.amed-wis" v36.01.15.001 (AMED Prüfungsverwaltung (WIS)) [INFO] Plugin found 1 plugin(s)
%schlüssel% stehen.Der Host baut einen Abhängigkeitsgraphen auf. Quellen für Abhängigkeiten sind:
dependencies — Explizite Add-in-Abhängigkeiten mit Id und Version.servicesConsumed — Der Host sucht das Add-in, das den entsprechenden Vertragsnamen in servicesProvided deklariert.Der Graph wird topologisch sortiert (Kahn-Algorithmus). Das Ergebnis ist die Aktivierungsreihenfolge: Abhängigkeiten werden vor ihren Konsumenten aktiviert.
Typische Log-Ausgabe:
[INFO] Plugin resolving dependencies [DEBUG] Plugin activation order: 2 plugin(s) [DEBUG] 1. wvds.core-services [DEBUG] 2. wvds.amed-wis
psError markiert. Error-Log mit den Ids.Noch bevor eine einzige DLL geladen wird, registriert der Host alle statischen Contributions aus den Manifesten. Für jeden deklarierten Command wird ein Lazy-Stub angelegt — ein Platzhalter-Handler, der bei der ersten Ausführung die Aktivierung des Add-ins auslöst.
Gleichzeitig fließen die Manifest-Contributions in die zentrale Contribution-Sammlung (TWvdSShellContributions), die der TWvdSContributionRouter anschließend an die UI-Komponenten verteilt:
TWvdSCommandRouter → CommandPaletteTWvdSMainMenu (Menüleiste)TWvdSShellToolbar (Haupt-Toolbar)TWvdSActivityBar + TWvdSSideBar (Seitenleiste)TWvdSCommandRouter (Tastenkürzel)Typische Log-Ausgabe:
[INFO] Plugin registering contributions for 1 plugin(s) [DEBUG] Plugin "wvds.amed-wis": 10 commands, 11 menus, 2 keybindings [INFO] Plugin contributions fed: 10 commands, 11 menus, 3 views [INFO] Routed 10 commands [DEBUG] TWvdSSideBar.RegisterView: id="wis.orgTree" title="ORGANISATIONSSTRUKTUR" [DEBUG] TWvdSSideBar.RegisterView: id="wis.filter" title="FILTER" [INFO] Routed 5 toolbar items
Beachtenswert: Die Oberfläche steht jetzt vollständig. Der Benutzer sieht alle Menüpunkte, Toolbar-Buttons, Sidebar-Panels und Tastenkürzel — obwohl keine einzige DLL geladen wurde. Das ist der zentrale Vorteil des deklarativen Contribution-Modells.
Die Aktivierung verläuft in zwei Varianten:
Add-ins mit activationEvents: [„onStartup“] werden sofort nach Phase 3 aktiviert. Das ist typisch für Sidebar-Panels, die beim Start sichtbar sein sollen.
Add-ins mit activationEvents: [„onCommand:mein.command“] werden erst beim ersten Aufruf des Commands aktiviert. Der Lazy-Stub fängt den Aufruf ab und löst folgende Schritte aus:
LoadLibrary lädt die DLL in den Prozess.GetAbiInfo wird aufgerufen. Der Host prüft Magic ($57564453), ABI-Version und FPC-Version.CreatePlugin(IHost) wird aufgerufen. Das Add-in erhält Zugriff auf alle Host-Services.IPlugin.Activate(IExtensionContext) wird aufgerufen. Das Add-in registriert echte Command-Handler, Document-Factories und Event-Abonnements.Typische Log-Ausgabe:
[INFO] Plugin lazy activation "wvds.amed-wis" by command "wis.proofExec.open" [DEBUG] Plugin DLL loaded: bin/WIS.Plugin.dll [DEBUG] Plugin ABI handshake: magic=$57564453, abi=1, fpc=30301 [INFO] Plugin "wvds.amed-wis" activated successfully
psError markiert.psError markiert.Beim Herunterfahren der Anwendung durchläuft jedes aktive Add-in die Deaktivierung:
Subscribe gesammelten IDisposable-Tokens werden in umgekehrter Reihenfolge (LIFO) aufgelöst. Command-Handler, Menüpunkte, Factories und Event-Abonnements werden entfernt.Die LIFO-Reihenfolge ist wichtig: Wenn ein Menüpunkt auf einen Command verweist, wird der Menüpunkt vor dem Command entfernt. Dadurch gibt es keine Dangling References.
| Symptom | Mögliche Ursache | Diagnose |
| Kein Log-Eintrag | Plugin-Verzeichnis nicht im Suchpfad | Prüfe, ob plugin.json in <exe>/plugins/<name>/ oder ~/.wvdsx/extensions/<name>/ liegt |
Plugin found 0 | Verzeichnis existiert nicht | Erstelle das Verzeichnis und kopiere plugin.json hinein |
invalid manifest | Pflichtfeld fehlt | Prüfe Log auf fehlende Felder (id, name, version, main) |
%displayName% in der UI | NLS-Datei fehlt oder package.nls.json enthält den Schlüssel nicht | Prüfe, ob package.nls.json alle %platzhalter% abdeckt |
| Symptom | Mögliche Ursache | Diagnose |
Kein Eintrag trotz Routed N commands | Command wurde nicht in contributes.commands deklariert | Prüfe plugin.json auf Tippfehler im Command-Namen |
Routed 0 commands | Contributions wurden nicht in die Routing-Pipeline gespeist | Prüfe Log auf Plugin contributions fed: N commands |
| Symptom | Mögliche Ursache | Diagnose |
DLL not found | main-Pfad im Manifest stimmt nicht mit der Datei überein | Prüfe main: „bin/MyPlugin.dll“ gegen die reale Dateistruktur |
ABI mismatch | DLL mit anderer FPC-Version kompiliert | Kompiliere mit derselben FPC-Version wie der Host |
CreatePlugin failed | Exception im Constructor | Starte im Debug-Modus: wdochost –debug-extension=mein.addin |
Weiter zur Architektur oder zurück zur Übersicht.