Zum Inhalt

Attribute

Ein Script kann, wie wir schon erfahren haben, verschiedenste Funktionen ausführen. Darum müssen wir im Programmcode hinterlegen, welche Funktion das Script bereitstellt. Es können auch mehrere Actions in einem Script vorhanden sein. So kann man z. B. eine Beschriftung automatisch erzeugen lassen. Außerdem kann für diese Action ein eigener Befehl im Menüband erzeugt werden. Dies ist alles innerhalb einer Datei möglich. In diesem Fall macht das auch Sinn, da der Befehl nicht ohne die dazugehörige Action ausgeführt werden kann. Es macht aber keinen Sinn, alle Actions in eine Datei zu packen, da es so schnell unübersichtlich wird.

Für unser erstes Beispiel verwenden wir das Attribut [Start]. Das ist der schnellste Weg, mehrere Scripte zu testen. Oftmals stellt sich die Frage, wann ein Script geladen und was ausgeführt werden muss. Über die Attribute können wir dies schnell und einfach herausfinden. Dies ist eine Auflistung der Attribute fürs Ausführen und Laden:

  • Ausführen: [Start]
  • Laden:
    • [DeclareAction]
    • [DeclareEventHandler]
    • [DeclareMenu]
    • [DeclareRegister]
    • [DeclareUnregister]

Scripte                   |

Start

Das Attribut [Start] wird meistens verwendet, wenn man ein Script nur einmal oder eher selten benötigt. Wir müssen bei jedem Starten der Action über die Backstage-Ansicht gehen, um das Script auszuführen. Alternativ verwenden wir die erstellten Befehle in unserer Registerkarte. In der Entwicklungsumgebung wechseln wir ins Codefenster und betrachten die ersten Zeilen. Wir führen hierfür einen Doppelklick auf die Datei 01_Start.cs aus.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

Mit dem Befehl using wird beschrieben, welche Verweise verwendet werden sollen. In einer sogenannten Using-Direktive werden bestimmte Programmbefehle gespeichert und können, sofern sie geladen sind, abgerufen werden. Für das erste Script sind folgende Verweise erforderlich:

  • System.Windows.Forms

  • Eplan.EplApi.Scripting

Es werden nicht immer alle Verweise benötigt. Dennoch ist es ratsam, eine Vorlage zu erstellen, die alle für uns wichtigen Using-Direktiven enthält. Später können wir die nicht benötigten Elemente entfernen. Folgende EPLAN-Namespaces stehen im Scripting zur Verfügung:

  • Eplan.EplApi.ApplicationFramework

  • Eplan.EplApi.Base

  • Eplan.EplApi.MasterData

  • Eplan.EplApi.Scripting

  • Newtonsoft.Json

  • System

  • System.Drawing

  • System.IO.Compression.FileSystem

  • System.Net.Http

  • System.Windows.Forms

  • System.Xml

  • System.Linq

Beim Tippen des Codes erscheint ein kleiner Dialog mit verschiedenen Begriffen. Diesen Dialog nennt man IntelliSense. Es ist eine Möglichkeit zur Wortvervollständigung einzelner Begriffe in der Programmierung. Das von Microsoft entwickelte Hilfsmittel ist in fast allen Entwicklungsumgebungen für sämtliche Programmiersprachen vorhanden. Wenn man einen Begriff eingibt, werden übereinstimmende Ergebnisse angezeigt. Wir können nun mit den Pfeiltasten auf der Tastatur den gewünschten Begriff auswählen. Um das Getippte zu vervollständigen, drücken wir auf die Tab Taste. Ist IntelliSense nicht sichtbar, kann der Dialog mit dem Tastatur-Shortcut Ctrl+Space wieder eingeblendet werden.

IntelliSense

Eine Code-Folge wird in C# immer mit einem Semikolon (;) beendet. Wer schon einmal in Visual Basic programmiert hat, weiß, dass es dort der Zeilenumbruch ist. In C# können wir beliebig viele Zeilenumbrüche im Code einfügen.

Den Aufbau eines Programmcodes in C# kann man sich vorstellen wie eine Zwiebel. Es gibt verschiedene Schichten, die mit geschweiften Klammern eingegrenzt werden. Der Aufbau ist allerdings nicht so kompliziert, dass die Zwiebel uns zum Weinen bringen wird.

 graph LR
   subgraph     id1["Namensraum (Namespace)"]
        subgraph id2["Klasse (Class)"]
            id3["Methode (Void)"]
        end
   end

Die „äußere Schale" ist der Namespace:

namespace Namespace
{

}

Die „mittlere Schale" ist die Klasse (Class):

class Class
{

}

Bei der Funktion, welche ausgeführt wird, spricht man von einer Methode. Methoden werden mit void gekennzeichnet. Wir ergänzen den Programmcode um folgende Zeilen:

void Function()
{

}

In der Funktion steht nun der eigentliche Programmcode (Was soll EPLAN tun?). Wir lassen eine MessageBox anzeigen, um festzustellen, ob unser Script ausgeführt wurde. Dies ist der Aufbau des Befehls in kurzen Worten:

  • Was soll gemacht werden? → MessageBox

  • Was soll damit angestellt werden? → Show (anzeigen)

  • Was soll angezeigt werden? → Scripting is great!

Die einzelnen Klassen und Methoden werden durch einen Punkt getrennt. Wir stellen uns hierzu eine Treppe vor. Auf jeder Ebene befinden sich andere Räume mit unterschiedlichen Funktionen. Zu Beginn findet man oft nicht sofort die gewünschte Funktion, aber mit der Zeit versteht man die Struktur des.NET Frameworks.

Beispielaufbau eines Methodenaufrufs:

Ebene0.Ebene1.Ebene2.Methode();

Nehmen wir als Beispiel eine Aktivität an einem Ort, müsste dies wie folgt angegeben werden:

München.Theresienwiese.Oktoberfest.Achterbahnfahren();

Text steht im Programmcode immer in Hochkommata ("Anführungszeichen"):

München.Bahnhof.Schaffner.Ruft("Alles einsteigen!");

Kommentare können mit zwei Schrägstrichen eingefügt werden:

// Ich bin ein Kommentar

Dadurch weiß das Programm, dass es sich um einen Kommentar handelt, der nicht abgearbeitet werden muss.

In Visual Studio gibt es fertige Buttons für das Einfügen von Kommentaren. Ist diese Toolbar nicht sichtbar, können wir diese über Toolbar > Kontextmenü > Text Editor einblenden. Es wird dann die komplette Zeile, welche gerade aktiv ist, ein- bzw. auskommentiert.

image-20250508084334586

Um eine MessageBox anzuzeigen, ist folgender Code notwendig:

MessageBox.Show("Scripting is great!"); // Comment

Eine Funktion wird mit return (zurückkehren) abgeschlossen.

return;

Nicht verwendete Verweise sollten wir entfernen, um das Script übersichtlicher zu machen. Durch einen rechten Mausklick und das Ausführen der Funktion Remove Unnecessary Usings in Visual Studio geschieht dies automatisch.

image-20250508084539147

Nun setzen wir unsere „Schalen" zusammen. Das komplette Beispiel ist immer am Ende einer Lektion zu finden:

using Eplan.EplApi.Scripting;
using System.Windows.Forms;

namespace Namespace
{
  public class Class
  {
    [Start]
    public void Function()
    {
      MessageBox.Show("Scripting is great!"); // Comment
      return;
    }
  }
}

Wir wechseln nun in die EPLAN-Software und testen das Script über Script ausführen in unserer Registerkarte. Im darauffolgenden Dialog wählen wir das Script aus. Die Scriptdatei befindet sich im Ordner des Visual Studio-Projekts.

Script ausführen

Wurde der Programmcode fehlerfrei ausgeführt, sieht man den in dargestellten Dialog.

image-20250508091420034

Beim Schreiben des Programmcodes können mehrere Fehler passieren. Wir kommentieren testweise die Initialisierung der Using-Direktiven aus:

//using System.Windows.Forms;
//using Eplan.EplApi.Scripting;

Vielleicht ist dir beim Auskommentieren der Using-Anweisungen schon aufgefallen, dass im Fehlerfenster von Visual Studio einige Fehler hinzugekommen sind. Dies resultiert aus der Tatsache, dass die Entwicklungsumgebung die Ausdrücke aufgrund fehlender Verweise nicht finden kann. Diese Fehlerliste ist ähnlich wie die Meldungsverwaltung von EPLAN aufgebaut. Hier wird ebenfalls unterschieden zwischen:

  • Fehlern
  • Warnungen
  • Mitteilungen

image-20250508091547482

Ist das Fenster aus nicht sichtbar, können wir es über View > Error List einblenden.

image-20250508092236680

Wenn wir nun das Script ausführen, müsste es eigentlich auch in EPLAN zu einem Fehler kommen. Im Falle von den fehlenden Using-Direktiven ist dies aber nicht immer der Fall, da diese bereits in EPLAN geladen sein können.

Um eventuell auftretende Fehler schnell zu finden, können wir über die Tools > Options > Text Editor > C# in Visual Studio auch die Zeilennummern einblenden, falls diese noch nicht sichtbar sind.

image-20250508092356514

Nun wollen wir einen weiteren Fehler provozieren: Gerade am Anfang vergisst man öfter mal, den Code mit einem Semikolon abzuschließen. Wenn die Fehlerliste eingeblendet ist, können wir dies schon vor dem Ausführen in EPLAN sehen. Im Code-Fenster wird die Stelle rot unterstrichen.

image-20250508104200216

Auch EPLAN überprüft den Code, bevor dieser geladen oder ausgeführt wird.

image-20250508104247000

image-20250508104328327

DeclareAction

Wollen wir eine Action häufiger verwenden, macht es Sinn, diese dauerhaft zu laden. Wir kopieren dazu das Script 01_Start.cs über Ctrl+C oder per Kontextmenü und fügen es auf Projektebene ein.

Die Datei benennen wir nun in 02_DeclareAction.cs um. Dann öffnen wir die Datei mit einem Doppelklick. Der Programmcode sieht logischerweise genauso aus wie im ersten Beispiel. In der Tab-Leiste erkennt man, welche Datei editiert wird.

Datei kopieren/einfügen

Um das neue Attribut festzulegen, editieren wir die Zeile [Start]. Diese schreiben wir in [DeclareAction("ActionName")] um. Um Konflikte von gleichen Klassen zu vermeiden, verwenden wir einen eindeutigen Namen für jedes Script im Projekt. In den folgenden Beispielen verwenden wir immer die Kombination aus Ordnername und Dateinamen für die Klasse. Der Namespace ist optional und wird in den Beispielen zur Vereinfachung weggelassen. Sofern es nicht nötig ist, lassen wir auch den return-Befehl am Ende des Scripts weg.

Info

Es dürfen keine führenden Zahlen für einen Namespace oder Klassen verwendet werden. Aus diesem Grund schreibt man z. B. _01_FirstSteps und nicht 01_FirstSteps.

using System.Windows.Forms;
using Eplan.EplApi.Scripting;

public class _01_FirstSteps_02_DeclareAction
{
  [DeclareAction("ActionName")]
  public void Function()
  {
    MessageBox.Show("Scripting is great!");
  }
}

DeclareAction zeigt, dass eine neue Action zu EPLAN hinzugefügt wird. ActionName ist der Name der neuen Action.

Nun laden wir das Script über den Befehl Script laden im Menüband in EPLAN. EPLAN gibt keine Rückmeldung über das erfolgreiche Laden eines Scripts. Bei einem Fehler werden jedoch, wie zuvor beschrieben, die Systemmeldungen angezeigt. Ist dies der Fall, analysieren bzw. vergleichen wir Zeile für Zeile. Als letzte Lösung können wir das fertige Script verwenden. Wir ändern den Programmcode und laden das Script erneut, bis keine Fehler in den Systemmeldungen mehr angezeigt werden. Gerade zu Beginn der Script-Programmierung kommt es häufiger vor, dass ein Script nicht auf Anhieb funktioniert.

Wir fügen nun in unsere Befehlsgruppe Test einen neuen Befehl ein. Hierfür setzen wir einen beliebigen Befehl aus der Kategorie Aktionen ein. Als Anzeigenamen wählen wir Meine Action und ersetzen den Inhalt der Textbox Befehlszeile durch ActionName. Bild, QuickInfo und Beschreibung sind nicht nötig. Betätigt man die Schaltfläche, erscheint die MessageBox erneut.

image-20250508105306889

Über Script entladen in unserer Registerkarte können wir einzelne Scripte entladen. In den folgenden Abschnitten werden wir mit dem gleichen Actionnamen arbeiten. Darum ist es ratsam, alle Scripte immer zu entladen, sobald wir einen Abschnitt abgeschlossen haben.

Script entladen

DeclareEventHandler

EPLAN stellt ein Attribut bereit, um eine Action zu einem bestimmten Zeitpunkt auszuführen. Wir kopieren wieder unsere Vorlage und benennen diese in 03_DeclareEventHandler.cs um. Als Attribut fügen wir Folgendes ein:

[DeclareEventHandler("onActionStart.String.XPrjActionProjectClose")]

Will man die Action z. B. beim Schließen eines Projekts ausführen, kann dieses Ereignis abgefangen werden.

  • DeclareEventHandler zeigt, dass ein Ereignis abgefangen werden muss
  • onActionStart.String.XPrjActionProjectClose gibt an, um welches Ereignis es sich handelt

Doch woher bekommen wir den Namen der internen EPLAN-Action? Leider gibt es keine Übersicht oder Ähnliches in der Hilfe. Es gibt allerdings einen Diagnose-Dialog in EPLAN, der uns die letzte Action anzeigt. Wir wechseln nach EPLAN und führen die gewünschte Action aus. Den Diagnose-Dialog erreichen wir über das Drücken von Ctrl+^. Wenn wir z. B. die Action zum Schließen eines Projekts herausfinden wollen, schließen wir ein beliebiges Projekt und drücken danach Ctrl+^. Nun erscheint der Diagnose-Dialog.

Info

Die Tastenkombination Ctrl+^ funktioniert nur mit deutschem Tastaturlayout. EPLAN verwendet hier den virtuellen Key-Code VK_OEM_5.

In diesem Beispiel ist für uns nur die erste Zeile wichtig:

Last called action from (context)menu: XPrjActionProjectClose

Hier finden wir den Namen der Action. Für das Abfangen muss man EPLAN allerdings noch mitteilen, um welchen Typ es sich handelt, wie z. B.:

  • onActionStart vor Ausführung der eigentlichen Action (Projekt schließen)
  • onActionEnd nach Ausführung der eigentlichen Action (Projekt schließen)

Mit String wird mitgeteilt, dass es sich um eine Zeichenkette handelt. Das machen wir mit onActionStart.String:

using System.Windows.Forms;
using Eplan.EplApi.Scripting;

public class _01_FirstSteps_03_DeclareEventHandler
{
  [DeclareEventHandler("onActionStart.String.XPrjActionProjectClose")]
  public void Function()
  {
    MessageBox.Show("Scripting is great!");
  }
}

Wir laden das Script nun in EPLAN. Schließt man ein beliebiges Projekt, sollte der Dialog erneut erscheinen.

DeclareRegister und DeclareUnregister

Die zwei Attribute DeclareRegister und DeclareUnregister fangen eigentlich auch jeweils ein Event ab. Diese Events sind jedoch abhängig vom Script.

  • DeclareRegister wird ausgeführt, wenn das Script geladen wird.

  • DeclareUnregister wird ausgeführt, wenn das Script entladen wird.

Dadurch können z. B. Dateien oder Daten sowie Einstellungen erstellt bzw. gelöscht werden.

Wir kopieren wieder unsere Vorlage (01_Start.cs) und vergeben den Namen 04_DeclareRegisterUnregister.cs. Diesmal müssen wir mehrere Anpassungen am Code vornehmen. Als Erstes ersetzen wir [Start] durch [DeclareRegister] und ändern den Text der MessageBox auf Script geladen. Die Methode wird mit Register benannt:

[DeclareRegister]
public void Register()
{
  MessageBox.Show("Script loaded.");
}

Als Nächstes kopieren wir die komplette Methode und fügen sie nach den geschweiften Klammern als Methode Register() ein. Diese Methode benennen wir UnRegister(). Es dürfen nämlich nicht mehrere Methoden mit dem gleichen Namen in einer Klasse vorhanden sein.

Nun fügen wir vor diese Methode das Attribut [DeclareUnregister] ein. Der Text der MessageBox wird auf Script entladen geändert. Wenn wir uns den Code ansehen, kann man vielleicht schon erahnen, was beim Laden des Scripts bzw. was beim Entladen passiert:

using System.Windows.Forms;
using Eplan.EplApi.Scripting;

public class _01_FirstSteps_04_DeclareRegisterUnregister
{
  [DeclareRegister]
  public void Register()
  {
    MessageBox.Show("Script loaded.");
  }

  [DeclareUnregister]
  public void UnRegister()
  {
    MessageBox.Show("Script unloaded.");
  }
}