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]
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.
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:
Die „mittlere Schale" ist die Klasse (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:
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:
Nehmen wir als Beispiel eine Aktivität an einem Ort, müsste dies wie folgt angegeben werden:
Text steht im Programmcode immer in Hochkommata ("Anführungszeichen"):
Kommentare können mit zwei Schrägstrichen eingefügt werden:
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.
Um eine MessageBox anzuzeigen, ist folgender Code notwendig:
Eine Funktion wird mit return
(zurückkehren) abgeschlossen.
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.
Nun setzen wir unsere „Schalen" zusammen. Das komplette Beispiel ist immer am Ende einer Lektion zu finden:
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.
Wurde der Programmcode fehlerfrei ausgeführt, sieht man den in dargestellten Dialog.
Beim Schreiben des Programmcodes können mehrere Fehler passieren. Wir kommentieren testweise die Initialisierung der Using-Direktiven aus:
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
Ist das Fenster aus nicht sichtbar, können wir es über View > Error List einblenden.
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.
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.
Auch EPLAN überprüft den Code, bevor dieser geladen oder ausgeführt wird.
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.
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.
Ü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.
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:
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 mussonActionStart.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:
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: