Addins für Sparx Enterprise Architect ohne Administratorrechte entwickeln und betreiben? – Ja, es geht!

In diesem Beitrag möchte ich zeigen, wie man Addins für Sparx Systems Enterprise Architect auch ohne Administratorrechte entwickeln und betreiben kann.

Ich selbst entwickle solche Addins immer mal wieder seit nunmehr 20 Jahren und mir war bis gestern nicht klar, dass es möglich ist diese auch ohne Administratorrechte zu entwickeln und zu betreiben. Aber es geht, wenn man weiß wie!

Wie funktionieren Addins für Enterprise Architect?

Die Modellierungsplattform Sparx Systems Enterprise Architect (EA) ist eine in C++ implementierte Windows-Anwendung und basiert auf der Microsoft COM-Technology (Component Object Model). Man kann die Anwendung über selbstgeschriebene Addins um neue Funktionalitäten erweitern. Diese Addins können mit COM, aber auch mit dem damit kompatiblen neueren .NET-Framework entwickelt werden. Das Addin wird dabei als eine Klassenbibliothek (DLL) erstellt und per Registry-Eintrag wird dem EA bekannt gegeben, dass es dieses Addin gibt.

Wenn EA startet, dann wird versucht die DLL zu laden und auszuführen. Das Plugin beginnt zu arbeiten. Dazu ist es allerdings notwendig, dass  der EA die DLL auch auf der Festplatte finden kann. Damit dies funktioniert muss man die DLL als „COM-sichtbar“ markieren und bei Betriebssystem registrieren (so genannte „COM-Registrierung“). Zu diesem Zweck gibt es von Microsoft das Werkzeug regasm.exe, das genau diese COM-Registrierung macht.

Nun ist es aber so, dass das Werkzeug regasm.exe die Registrierung nur erfolgreich durchführen kann, wenn man Administratorrechte hat. Zumindest sagt das die Fehlermeldung die man bekommt, wenn man es ohne Administratorrechte ausführt:

C:\work\MDD4All.UserRegistredAddin\MDD4All.UserRegistredAddin\bin\Debug>c:\Windows\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe /codebase MDD4All.UserRegistredAddin.dll

Microsoft .NET Framework Assembly Registration Utility 4.8.9032.0

für Microsoft .NET Framework, Version 4.8.9032.0

Copyright (C) Microsoft Corporation. Alle Rechte vorbehalten.

RegAsm : error RA0000 : Fehler beim Schreiben der Registrierungsinformationen in die Registrierung. Zur Verwendung der ausgewählten Optionen sind Administratorrechte erforderlich. Verwenden Sie einen Administratorbefehl, um diese Aufgaben abzuschließen.

 

Wie kann man nun dieses Problem lösen?

Dazu muss man verstehen was bei einer COM-Registrierung passiert. Es werden von regasm.exe verschiedene Registry-Einträge erstellt, die die Informationen über die registrierte DLL enthalten, in die Registry geschrieben. Diese werden in den Bereich HKLM (=Computer) abgelegt. Auf diesen Bereich haben allerdings Benutzer ohne Administratorrechte normalerweise keinen schreibenden Zugriff. Daher funktioniert der Befehl auch nicht ohne erhöhte Rechte.

COM-Registrierung ohne  Administratorrechte?

Auf der Suche, ob man eine COM-Registrierung auch ohne Administratorrechte machen kann, stößt man darauf, dass es möglich sein soll, die notwendigen Registrierungen statt im Bereich des Computers (HKLM) statt dessen im Bereich des aktuellen Benutzers zu machen (HKEY_CURRENT_USER). Die Anwendungen suchen auch in diesem Bereich nach COM-Registrierungsinformationen.

Um jetzt eine COM-Registrierung in den Bereich des Benutzers zu schreiben anstatt des Computers bietet regasm.exe glücklicherweise die Option /regfile an. Damit werden die Registrierungsschlüssel nicht direkt in die Registry geschrieben, sondern in eine .reg-Datei gespeichert, die man verändern und dann ausführen kann. Es wird so möglich die Ziele der Registrierungsschlüssel manuell zu verändern und die COM-Komponente im Benutzerbereich, den man auch beschreiben darf durchzuführen. Einen guten Hinweis, dass dies dann auch mit Enterprise Architect Addins funktionieren sollte gibt auch die Seite AddInWithoutAdmin · Helmut-Ortmann/EnterpriseArchitect_hoTools Wiki (github.com).

Schritt für Schritt zum EA-Addin ohne notwendige Administratorrechte

Mit dem oben beschriebenen Wissen über die COM-Registrierung kann man nun ein EA-Addin Schritt für Schritt aufsetzen. Die Umgebung sieht dabei folgendermaßen aus:

  • Enterprise Architect 32-Bit Version. Installiert unter C:\Program Files (x86)\Sparx Systems\EA\EA.exe
  • Visual Studio 2022
  • .NET Framework 4.8
  • Keine Administratorrechte vorhanden

Man geht nun folgendermaßen vor:

  • Visual Studio starten
  • Neues Projekt erstellen

  • Die Class1 in EaAddin umbenennen (im Code und der Datei)
  • In der Klasse wird ein Anfang für ein Addin programmiert, dass ein Menü anzeigt:
namespace MDD4All.UserRegistredAddin
{
    public class EaAddin
    {

        private const string MENU_HEADER = "-&Addin w/o Admin";

        private const string MENU_ACTION1 = "&Action 1";
        private const string MENU_ACTION2 = "&Action 2";

        public object EA_GetMenuItems(EA.Repository repository,
                                      string menuLocation,
                                      string menuName)
        {
            object result = "";

            switch (menuName)
            {
                case "":
                    result = MENU_HEADER;
                    break;

                case MENU_HEADER:
                    result = new string[] { MENU_ACTION1, MENU_ACTION2 };
                    break;
            }

            return result;
        }
    }
}
  • Nun muss unter den Projekteigenschaften (Eigenschaften –> Anwendung –> Assemblyinformationen…) die Option „Assembly COM-sichtbar machen“ aktiviert werden.

  • Damit das Assembly einen starken Namen (strong name) für die COM-Registrierung bekommt, muss man es außerdem signieren (Eigenschaften –> Signierung).
  • Nun das Projekt übersetzen.
  • Damit der Enterprise Architect das Addin findet, muss man es in die Registry eintragen (<Namespace>.<Klassenname>):

  • Wenn man nun den EA startet, kann das Addin nicht geladen werden, da die COM-Registrierung noch fehlt. Es erscheint im EA als „Error – Missing“:

Die COM-Registrierung

Nun erfolgt die modifizierte COM-Registrierung. Dazu wird im ersten Schritt mit Hilfe der Kommandozeile regasm.exe ausgeführt und eine passende .reg-Datei generiert:

  • C:\work\MDD4All.UserRegistredAddin\MDD4All.UserRegistredAddin\bin\Debug>c:\Windows\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe /codebase /regfile MDD4All.UserRegistredAddin.dll

    Microsoft .NET Framework Assembly Registration Utility 4.8.9032.0

    für Microsoft .NET Framework, Version 4.8.9032.0

    Copyright (C) Microsoft Corporation. Alle Rechte vorbehalten.

    Das Registrierungsskript „C:\work\MDD4All.UserRegistredAddin\MDD4All.UserRegistredAddin\bin\Debug\MDD4All.UserRegistredAddin.reg“ wurde generiert.

 

  • Die generierte .-reg-Datei sieht so aus: Sie besteht dabei aus 7 Einträgen. Die ersten beiden definieren die zu registrierende Klasse und vergeben für diese eine eindeutige ID (hier {E961C205-523D-3365-A56E-1B3387E60C82}). Die nachfolgenden 5 Einträge beschreiben dann die DLL und deren Position im Dateisystem des Rechners.
REGEDIT4

[HKEY_CLASSES_ROOT\MDD4All.UserRegistredAddin.EaAddin]
@="MDD4All.UserRegistredAddin.EaAddin"

[HKEY_CLASSES_ROOT\MDD4All.UserRegistredAddin.EaAddin\CLSID]
@="{E961C205-523D-3365-A56E-1B3387E60C82}"

[HKEY_CLASSES_ROOT\CLSID\{E961C205-523D-3365-A56E-1B3387E60C82}]
@="MDD4All.UserRegistredAddin.EaAddin"

[HKEY_CLASSES_ROOT\CLSID\{E961C205-523D-3365-A56E-1B3387E60C82}\InprocServer32]
@="mscoree.dll"
"ThreadingModel"="Both"
"Class"="MDD4All.UserRegistredAddin.EaAddin"
"Assembly"="MDD4All.UserRegistredAddin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=dfd4bdb117292732"
"RuntimeVersion"="v4.0.30319"
"CodeBase"="file:///C:/work/MDD4All.UserRegistredAddin/MDD4All.UserRegistredAddin/bin/Debug/MDD4All.UserRegistredAddin.dll"

[HKEY_CLASSES_ROOT\CLSID\{E961C205-523D-3365-A56E-1B3387E60C82}\InprocServer32\1.0.0.0]
"Class"="MDD4All.UserRegistredAddin.EaAddin"
"Assembly"="MDD4All.UserRegistredAddin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=dfd4bdb117292732"
"RuntimeVersion"="v4.0.30319"
"CodeBase"="file:///C:/work/MDD4All.UserRegistredAddin/MDD4All.UserRegistredAddin/bin/Debug/MDD4All.UserRegistredAddin.dll"

[HKEY_CLASSES_ROOT\CLSID\{E961C205-523D-3365-A56E-1B3387E60C82}\ProgId]
@="MDD4All.UserRegistredAddin.EaAddin"

[HKEY_CLASSES_ROOT\CLSID\{E961C205-523D-3365-A56E-1B3387E60C82}\Implemented Categories\{62C8FE65-4EBB-45E7-B440-6E39B2CDBF29}]
  • Nun erfolgt die Ersetzung von HKEY_CLASSES_ROOT durch die entsprechenden Benutzerbereiche innerhalb der Registry.
  • Man ersetzt also HKEY_CLASSES_ROOT mit HKEY_CURRENT_USER\Software\Classes

Achtung Falle 32 Bit!

Wenn man die Ersetzung oben macht und dann die Registrierungsdatei ausführt werden die Daten alle in die Registry geschrieben. Leider findet dann der Enterprise Architect immer noch nicht das Addin. 🙁 Dies liegt daran, dass die Klassen auf einem 64 Bit betriebssystem auch für 64 Bit Umgebungen registriert werden. Enterprise Architect ist jedoch  in der 32 Bit Version installiert.

In der Registry gibt es für Klassen, die für 32 Bit registriert werden sollen einen eigenen Bereich, der als  WOW6432Node bezeichnet wird. Genau dort muss man auch die DLL-Informationen hinterlegen, damit das Addin dann auch gefunden werden kann.

  • Es benötigt daher noch folgende Ersetzung in der .reg-Datei: Ersetzen von Classes\CLSID mit Classes\WOW6432Node\CLSID und Speichern
  • Es ergibt sich für unser Beispiel folgende .reg-Datei als Resultat:
REGEDIT4

[HKEY_CURRENT_USER\Software\Classes\MDD4All.UserRegistredAddin.EaAddin]
@="MDD4All.UserRegistredAddin.EaAddin"

[HKEY_CURRENT_USER\Software\Classes\MDD4All.UserRegistredAddin.EaAddin\CLSID]
@="{E961C205-523D-3365-A56E-1B3387E60C82}"

[HKEY_CURRENT_USER\Software\Classes\WOW6432Node\CLSID\{E961C205-523D-3365-A56E-1B3387E60C82}]
@="MDD4All.UserRegistredAddin.EaAddin"

[HKEY_CURRENT_USER\Software\Classes\WOW6432Node\CLSID\{E961C205-523D-3365-A56E-1B3387E60C82}\InprocServer32]
@="mscoree.dll"
"ThreadingModel"="Both"
"Class"="MDD4All.UserRegistredAddin.EaAddin"
"Assembly"="MDD4All.UserRegistredAddin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=dfd4bdb117292732"
"RuntimeVersion"="v4.0.30319"
"CodeBase"="file:///C:/work/MDD4All.UserRegistredAddin/MDD4All.UserRegistredAddin/bin/Debug/MDD4All.UserRegistredAddin.dll"

[HKEY_CURRENT_USER\Software\Classes\WOW6432Node\CLSID\{E961C205-523D-3365-A56E-1B3387E60C82}\InprocServer32\1.0.0.0]
"Class"="MDD4All.UserRegistredAddin.EaAddin"
"Assembly"="MDD4All.UserRegistredAddin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=dfd4bdb117292732"
"RuntimeVersion"="v4.0.30319"
"CodeBase"="file:///C:/work/MDD4All.UserRegistredAddin/MDD4All.UserRegistredAddin/bin/Debug/MDD4All.UserRegistredAddin.dll"

[HKEY_CURRENT_USER\Software\Classes\WOW6432Node\CLSID\{E961C205-523D-3365-A56E-1B3387E60C82}\ProgId]
@="MDD4All.UserRegistredAddin.EaAddin"

[HKEY_CURRENT_USER\Software\Classes\WOW6432Node\CLSID\{E961C205-523D-3365-A56E-1B3387E60C82}\Implemented Categories\{62C8FE65-4EBB-45E7-B440-6E39B2CDBF29}]

  • Startet man diese .reg-Datei und wendet sie an, dann kann der EA das Addin finden und ausführen:

Debugging funktioniert auch

Man kann nun auch im Visual Studio noch den Debugger aktivieren. Dazu trägt man unter den Projekteigenschaften –> Debuggen den Enterprise Architect als zu startendes externes Programm ein:

Wenn man das Debugging startet kann man nun wie gewohnt Breakpoints setzen und Variablen anschauen.

Fazit

EA-Addins lassen sich durch „Umbiegen“ der COM-Registrierung auch ohne Administratorrechte entwickeln und betreiben. Das Beispiel zeigt, dass 20 Jahre als sicher geglaubtes Wissen sich auch mal als falsch herausstellen kann und es doch Lösungen für Probleme geben kann, die man als so nicht lösbar eingestuft hatte :-).

Wiederbelebung des MDD4All.de Blogs

Lange war es still auf meinem Blog. Viele andere Dinge, sowohl beruflicher als auch privater Natur, hatten höhere Priorität. Ich habe mir nun aber vorgenommen ab diesem Jahr wieder öfter Beiträge zu den Themen Systems und Software Engineering zu schreiben.

Vor einigen Monaten habe ich außerdem firmenintern meine Rolle verändert. Ich bin seit Februar nun als hauptamtlicher Ausbilder bei KARL MAYER für die Ausbildung im Bereich Informatik und IT für die Berufsausbildung der Fachinformatikerinnen und Fachinformatiker verantwortlich.  Hier gehört es zu meinen Aufgaben Themen und Wissen zu vermitteln. Daher fügt sich mein Blog als eine zusätzlich nutzbare Informationsquelle hier auch ganz gut ein.

Themen der letzten Jahre

In den letzten drei Jahren habe ich mich insbesondere mit zwei Themen auseinandergesetzt, über die ich in kommenden Beiträgen detaillierter schreiben will:

Software Engineering mit .NET

Softwareentwicklung mit .NET und hier insbesondere auch der Anwendung der relativ neuen Blazor-Technologie für Web-Frontend-Anwendungen mit C# und HTML war eines der Themen welches ich sowohl beruflich, als auch ehrenamtlich vorangetrieben habe.

SpecIF

Als aktives Mitglied der Arbeitsgruppe PLM4MBSE (Product-Lifecycle Management for Model Based Sytems Engineering) innerhalb der Gesellschaft für Systems Engineering (GfSE e.V.) habe ich an der Definition, Weiterentwicklung und Standardisierung der Specification Integration Facility (SpecIF) gemeinsam mit meinem lieben Kollegen Dr. Oskar von Dungern mitgewirkt. Die Initiative adressiert die Problematik des schwierigen Datenaustausches innerhalb des Produktlebenszyklus eines Produktes. Mit SpecIF sollen Probleme wie der Datenaustauch zwischen verschiedenen Werkzeugen und verschiedenen Projektbeteiligten und damit entstehende Medienbrüche zukünftig vermieden werden. Weitere Informationen zu SpecIF sollen später hier folgen.

An dieser Stelle nur so viel: SpecIF ist ein Datenformat und ein Begriffsmodell/Vokabular mit dem man Daten und Informationen, die während der Entwicklung und dem Betrieb eines Produktes/Systems entstehen, abbilden, austauschen und integrieren kann. Im letzten Jahr habe ich auch ein Tutorial beim Tag des Systems Engineering gehalten. Die Folien dazu gibt es hier: SpecIF Tutorial

SpecIF und .NET praktisch kombiniert

Durch Kombination der beiden Themen – SpecIF und .NET-Entwicklung – habe ich in den letzten Jahren eine umfangreiche Sammlung von Softwarebibliotheken und Anwendungen realisiert, welche als SpecIF-Referenzimplementierung gelten können. Diese Werkzeuge und Bibliotheken – durchweg realisiert mit .NET – ermöglichen praktische Anwendungen mit SpecIF wie die Erstellung von Anforderungsspezifikationen, Testfällen oder anderer Projektdokumentationen und -spezifikationen.

Alles ist Open-Source

Sämtliche Ergebnisse dieser Entwicklungen stehen als Open-Source auf Github unter MIT-Lizenz zur Verfügung und können damit für kommerzielle und nichtkommerzielle Zwecke genutzt werden.

Weitere Informationen

Weitere Informationen zu SpecIF und der von mir entwickelten Software „SpecIFicator“ finden sich auf www.specificator.com.

TypeScript–das bessere JavaScript!

Ich habe mich mit Webprogrammierung immer schwer getan. Insbesondere mit JavaScript konnte ich mich nie richtig anfreunden. Warum das so ist? Na ja. Ich habe von Anfang an seit ich programmiere, immer mit streng typisierten Programmiersprachen wie Java oder C# gearbeitet. Hier ist alles genau definiert und man muss – zumindest vor der Einführung von var – immer angeben von welchem Typ genau eine Variable ist.

Auch die Eigenart von JavaScript die Sichtbarkeit von Variablen nicht an einen durch geschweifte Klammern definierten Block zu koppeln, ist etwas, was ich erst mal ungläubig zur Kenntnis nehme.

Ich habe schon ein paar Anläufe gemacht mich mit JavaScript näher zu befassen, aber irgendwie wurden wir nie richtige Freunde. Anfang des Jahres habe ich ein neues Projekt übernommen, bei welchem die JavaScript-Umgebung Node.js zum Einsatz kam. In dem Projekt wurde allerdings nicht mit JavaScript programmiert, sondern mit TypeScript. Diese Sprache kannte ich vorher nicht und ich musste mich erst mal schlau machen, um was es sich dabei handelt.

TypeScript ist eine von Microsoft vorangetriebene Programmiersprache und eine Obermenge von JavaScript. Das bedeutet, dass JavaScript komplett in TypeScript enthalten ist. Aber das tolle daran ist, dass TypeScript genau das bietet was Leute wie ich an JavaScript vermissten, nämlich die Möglichkeit der Typisierung, Blocksichtbarkeit von Variablen mit dem Schlüsselwort let, die Möglichkeit Klassen und Sichtbarkeiten zu definieren wie in einer objektorientierten Sprache und noch vieles mehr.

Der TypeScript-Compiler liest dann die TypeScript Dateien ein und macht daraus wieder JavaScript Code. Dieser kann ganz normal bei Webseiten, Servern oder in Node.js verwendet werden, denn alle erweiterten Konstrukte werden in pures JavaScript übersetzt.

Ich habe selbst mehrfach die Erfahrung gemacht mit JavaScript schier zu verzweifeln, aber mit TypeScript schneller und sauberer ein Ergebnis zu erreichen. Der Code ist dabei viel verständlicher und  besser wartbar als JavaScript mit der selben Funktionalität. Daher kann ich, sofern Sie es nicht bereits kennen und irgendetwas im JavaScript Umfeld machen wollen, nur empfehlen sich auf jeden Fall TypeScript einmal genauer anzusehen.

Hier noch ein paar Links: