GetModulePara in C# verwenden

Ein TcCOM-Objekt stellt seine Parameter über das Interface ITcModuleInstance bereit. Jeder Parameter wird über eine numerische **Parameter-ID (PID)** angesprochen, die aus der TMC-Beschreibung des Moduls stammt. Dieser Artikel zeigt, wie man Parameterwerte über das Automation Interface in C# ausliest und dabei korrekt in den richtigen .NET-Typ überführt.

Der zentrale Stolperstein: GetModulePara liefert die Daten typlos als rohe Bytes zurück. Ohne Kenntnis des Parametertyps lassen sich diese Bytes nicht sinnvoll interpretieren. Die folgenden drei Regeln zeigen, wie man je nach Situation zum richtigen Wert kommt.

Voraussetzungen

Voraussetzung ist ein geöffnetes TwinCAT-Projekt mit einem TcCOM-Objekt, dessen Tree-Item bereits vorliegt. In den Beispielen ist treeItem das per LookupTreeItem ermittelte Objekt, das zu ITcModuleInstance gecastet wird:

var mi = (ITcModuleInstance)treeItem;

Die verwendete pid (z.B. 0x050300B1) ist die Parameter-ID aus der TMC-Beschreibung des Moduls.

Was GetModulePara zurückgibt

GetModulePara gibt einen VARIANT zurück, der ein Byte-Array mit VT_ARRAY | VT_UI1 enthält. Das sind rohe Bytes im Little-Endian-Format, ohne Typinformation. In C# kommt dieser VARIANT als byte[] an.

Weil die Bytes keine Typinformation tragen, muss der Aufrufer wissen, wie viele Bytes der Parameter belegt und wie sie zu deuten sind. Ohne die TMC-Beschreibung des Moduls — oder einen vorherigen Aufruf von GetTypeOfModulePara — sind die Bytes nicht korrekt zu interpretieren.

Welche Funktion für welchen Fall

Die folgende Tabelle fasst zusammen, welche der drei Zugriffsfunktionen sich für welchen Parametertyp eignet:

Situation

Empfehlung

Parameter ist BOOL, BYTE, WORD, DWORD, UDINT, UINT, INT (≤ 4 Byte)

GetModuleParaDWORD

Parameter ist LREAL (8 Byte), LINT (8 Byte) oder ein Struct

GetModulePara + BitConverter

Typ ist unbekannt

GetTypeOfModulePara vorher aufrufen

GetModuleParaDWORD für skalare Parameter

Für alle skalaren Parameter bis zu 4 Byte Größe ist GetModuleParaDWORD die einfachste Wahl. Die Funktion liefert direkt einen uint, sodass Byte-Arrays nicht notwendig sind. Der Rückgabewert wird anschließend auf den tatsächlichen Typ des Parameters gecastet:

var mi = (ITcModuleInstance)treeItem;
uint pid = 0x050300B1;

uint rawValue = mi.GetModuleParaDWORD(pid);

// Cast according to type:
int  asInt   = (int)rawValue;
bool asBool  = rawValue != 0;

GetModulePara + BitConverter für größere Typen

Parameter mit mehr als 4 Byte — etwa LREAL (8 Byte) oder LINT (8 Byte) — sowie Structs lassen sich nicht über GetModuleParaDWORD lesen. Hier holen Sie das rohe Byte-Array über GetModulePara und wandeln es mit BitConverter in den Zieltyp um. Wichtig ist, die zum Parametertyp passende BitConverter-Methode zu wählen, da die Bytes im Little-Endian-Format vorliegen:

var mi = (ITcModuleInstance)treeItem;
uint pid = 0x050300B1;

byte[] bytes = (byte[])mi.GetModulePara(pid);

// LREAL (= double, 8 bytes):
double position = BitConverter.ToDouble(bytes, 0);

// LINT (= long, 8 bytes):
long lint = BitConverter.ToInt64(bytes, 0);

// DINT (= int, 4 bytes):
int dint = BitConverter.ToInt32(bytes, 0);

GetTypeOfModulePara + ITcTypeInstance.Name

Ist der Typ eines Parameters zur Entwicklungszeit nicht bekannt, lässt er sich zur Laufzeit über GetTypeOfModulePara ermitteln. Die Funktion liefert ein ITcTypeInstance-Objekt, dessen .Name-Eigenschaft den Typnamen direkt als lesbaren String zurückgibt — ein Vergleich gegen Magic Numbers ist nicht nötig. Mit diesem Typnamen wählen Sie anschließend die passende Konvertierung für das von GetModulePara gelieferte Byte-Array:

var mi = (ITcModuleInstance)treeItem;
uint pid = 0x050300B1;

mi.GetTypeOfModulePara(pid, out ITcTypeInstance typeInstance);
string typeName = typeInstance.Name; // e.g. "LREAL", "UDINT", "BOOL", "DINT"

byte[] bytes = (byte[])mi.GetModulePara(pid);

object value = typeName switch {
    "LREAL"            => BitConverter.ToDouble(bytes, 0),
    "LINT"             => BitConverter.ToInt64(bytes, 0),
    "DINT"             => BitConverter.ToInt32(bytes, 0),
    "UDINT" or "DWORD" => BitConverter.ToUInt32(bytes, 0),
    "INT"              => BitConverter.ToInt16(bytes, 0),
    "UINT" or "WORD"   => BitConverter.ToUInt16(bytes, 0),
    "BOOL"             => bytes[0] != 0,
    _                  => bytes  // Struct or unknown type — return raw bytes
};

Der _-Zweig fängt Structs und unbekannte Typen ab und gibt das rohe Byte-Array zurück. Für zusammengesetzte Typen lässt sich der genaue Aufbau bei Bedarf über ITcTypeInstance.IecDeclaration ermitteln und das Byte-Array entsprechend zerlegen.

GetModulePara in C# verwenden 1:

Damit ist Regel 3 der robusteste Weg, wenn der Parametertyp zur Entwicklungszeit nicht feststeht. Er funktioniert für alle skalaren Typen ohne vorheriges Wissen über die Bytegröße. Für bekannte skalare Parameter bleibt Regel 1 die einfachste Lösung. Details zum zurückgegebenen Typdeskriptor finden sich im Artikel ITcTypeInstance.