Readme "Windows-Front-End für Unix-Administration"

Nicht nur Kaviar

Dirk Anderseck

Zwar läßt sich das Binary direkt auf einem Windowsrechner installieren, wer aber selbst Hand anlegen möchte, dem hilft eine zusätzliche Beschreibung der einzelnen Programmteile.

Die Anwendung hier im Beispiel unterstützt als "richtige" Windows-Anwendung die Skalierung des Arbeitsbereichs. Nach der Größenänderung des Fensters durch den Anwender ruft Windows die Funktion FormResize() auf, die alle enthaltenen Objekte an die neuen Dimensionen anpaßt.

Bei einfachen Formulare mit wenigen Komponenten läßt sich die Anpassung automatisch durchführen, indem die Komponenten die Eigenschaft Alignment=alClient erhalten. Bei komplexeren Formularen sollten Sie die Komponentengröße manuell in der Funktion FormResize() berechnen. Das TForm-Objekt bietet hierzu auch die Eigenschaft ClientHeight und ClientWidth an. Sie enthalten die aktuelle Größe des Fensterinnenbereichs.

Die VCL Komponente TStringGrid dient sowohl der tabellarischen Anzeige, als auch der Speicherung empfangener Daten. Das Cells-Array dort bietet hierfür ausreichend Platz: Größe des Gitters, Überschriften und Inhalte lassen sich dynamisch verwalten.

ActiveX für die Grafik

UpdateDiskSheet() füllt das Diagramm mit Daten. Die ActiveX Komponente TVtChart erzeugt die Grafik. Sie bietet allerlei Möglichkeiten für zwei- oder dreidimensionale Balken- und Tortendiagramme. Die anzuzeigenden Daten stammen aus diskgrid und werden an chart übermittelt. Da letzteres eine ActiveX-Komponente ist, erwartet es einige Werte vom Typ Variant der mehrere Datentypen unterstützt, speziell für die Kommunikation mit Microsoft ActiveX Objekten.

Im "Server" findet die Definition der Anzahl von Spalten, Position der Datenfelder und Überschriften der tabellarischen Anzeigen statt, die er an PrepareGrid() sendet.

Der Server sendet beispielsweise den String:

DF|1024|1|Platte;A;0|1024-Blöcke;N;1
mit echo auf die Standardausgabe. Das erste Feld enthält das Kommando, in diesem Fall df (DiskFree). Danach folgt ein optionaler Parameter, der für df die logische Größe eines Plattenblocks definiert. Der nächste liefert die Anzahl an Kopfzeilen, die beim df-Kommando erscheinen, denn diese brauchen ja nicht angezeigt werden. Den Abschluß bilden die einzelnen Feldbeschreibungen mit Name, Datentyp und Position im Satz. Sie können die Postition entweder als Index des Wortes im Satz definieren, oder mit Startposition und Länge bezeichnen.

Soll Gridcontrol in einem anderen Fall die Spalten "Filesystem" und "Mounted on" anzeigen, kann der Formatstring mit Wortpositionen aufgebaut sein:

DF|512|1|Dateisystem;A;0|Name;A;5
Es geht aber auch mit Bytepositionen:
DF|512|1|Dateisystem;A;0;14|Name;A;58;20
Das zweite Subfeld mit "Datentyp" wird in diesen Beispielen nicht verwendet (ignoriert). Wenn in der Längenangabe im Feld "Name" anstatt 20 eine 0 steht, erscheint der String bis zum Zeilenende.

Der Windows Socket Aufruf recv() (Zeile 96 dtcp.cpp) empfängt den String in einem Puffer. Mit einem Aufruf von recv() können sowohl ein oder mehrere Sätze aber auch Satzfragmente empfangen werden. In Zeile 107 bis 122 hebt das Programm diese durch das Netzwerk entstandene Fragmentierung wieder auf, so daß OnTcpData() den Datensatz als eine Informationseinheit empfängt. Diese Funktion schickt eine Windows Message WM_TCPDATA an die Message Queue des Zielfensters. Von Dort gelangt sie zur Funktion TfrmKaviar::OnTcpData (Tmessage&msg) (191 fkaviar.cpp). Die Statusvariable CurrentCmd steht auf CMD, und daher erreicht der Datenpuffer ServerCommand().

Vorher hat SplitField() eine Aufteilung des Puffers in einzelne Felder durchgeführt. Der Grund, weshalb hier den C-Datentyp char * steht, liegt in der Effizienz des Codes. Alle durch recv() empfangenen Daten bleiben in dem einen Puffer, den die Funtkion selbst zur Verfügung stellt. Die Feldtrennzeichen werden dort durch Stringendezeichen (0) ersetzt, was unnötiges Kopieren vermeidet. Erst der endgültige Speicherort der Felder, das Cells Array des Gridcontrols, erfordert ein Kopieren vom Puffer in das String-Objekt.

Zum indizierten Zugriff auf die einzelnen Felder des Puffers dient ein Array vom Typ char *, gefüllt mit Zeigern auf jedes Puffer-Feld. ServerCommand() (301 fkaviar.cpp) prüft das erste Feld mit dem Kommando. Bei einem df geht es zur Funktion PrepareGrid().

Jede Feldinformation besteht aus einem Feldnamen, einem Feldtyp (der wird hier nicht benötigt) und einem Index, der der Wortposition im Datensatz entspricht. Alternativ kann dort auch anstatt des Index die Position und die Länge in Byte stehen.

Das globale Object vom Typ DfieldDesc letzlich speichert die Beschreibung.

Quellen für Kaviar

Kaviar.cpp

Dieser Sourcecode stammmt komplett aus dem C++Builder und enthält die Funktionen zum Instanzieren der verwendeten Formulare sowie Aufruf der Funktion Application->Run(), die für den gesamten Ablauf des Programms sorgt. Programmierer, die schon einmal ein Windows-Programm in herkömmlichem "C" geschrieben haben, kennen eine Schleife, die Windows-Botschaften empfängt und an die Fensterprozeduren weiterleitet. Diese Aufgabe übernimmt die Visual Control Library (VCL). Für jede Windows-Botschaft ruft VCL eine Funktion im betreffenden Formular-Objekt auf.

Fkaviar.cpp (fkaviar.h, fkaviar.fm)

Das Hauptformular der Anwendung ist ein von der VCL-Klasse TForm abgeleitetes Objekt mit dem Namen TfrmKaviar. Jede Formularklasse enthält Zeiger auf alle von der Entwicklungsumgebung eingefügten Komponenten, Methoden und Ereignisse. Der Code für die eingefügten Komponenten wird automatisch erzeugt. Programmierer können die Eigenschaften aller VCL-Objekte mit dem Objektinspektor der Entwicklungsumgebung einstellen und zur Laufzeit mittels C-Code verändern. Sie gehören aber nicht zur C++-Klasse TForm, sondern stehen als Pascal-Objekte in einer gesonderten Datei mit dem Namen fkaviar.dfm - der C++ Builder kann seine Delphi-Herkunft nicht ganz verschweigen.

Flogin.cpp (flogin.h, flogin.dfm)

Für die Anmeldung benötigt das Programm die Parameter "Host, Username, Paßwort und Programmname". Die Klasse Tfrmlogin enthält hierfür ein Dialogformular. Die Methode Execute() sorgt für den Datenaustausch mit der Anwendung und den modalen Aufruf der Dialogbox.

Dtcp.cpp (dcpp.h)

Die Netzwerkschnittstelle "Windows-Socket" ist in der Klasse DTcpClient gekapselt. Die AsyncConnect()-Methode startet einen eigenen Thread für Netzwerkoperationen.

Die Anwendung basiert auf einigen globalen Objekten, instanziert in der Datei fkaviar.cpp. Ein Hinweis zur Namensgebung: C++Builder Klassen aus der VCL beginnen mit "T", eigene Klassen beginnen mit "D".

Mögliche Erweiterungen

Wer eigene Erweiterungen einbauen möchte, kann Sie in folgenden Schritten vorgehen:

1. Einfügen einer neue Seite im PageCtrl des Hauptformulars, Vergabe eines Namen für die Seite und Einbauen eines GridControl in die neue Seite.

2. Anpassen der aktuellen Größe des GridControl an die Seitengröße in Fkaviar.cpp (Zeile 95),

3. Deklarieren einer weiteren DFieldDesc-Klasse für ein neues Kommando in Fkaviar.cpp (Zeile 21). Hier wird später die Datenformat-Information enthalten sein.

4. Erweitern des Enumerator CurrentCmd um einen Namen für das neue Kommando in Fkaviar.h (Zeile 78).

5. Fkaviar.cpp Zeile 212: Nach Empfang des Endesatzes teilen Sie Ihrem GridControl die Anzahl Zeilen mit, die empfangen wurden.

6. Fkaviar.cpp Zeile 246: Erweitern Sie die switch-Anweisung für einen Datensatz Ihres Kommandos. Geben Sie dazu den Namen Ihres GridControls und Ihrer Formatbeschreibung an.

7. Fkaviar.cpp Zeile 336: Erweitern Sie die switchAnweisung für einen Formatsatz Ihres Kommandos.

8. Fkaviar.cpp Zeile 423: Wenn auf Ihre neue Seite im Formular geschaltet wurde, müssen die Daten vom Server angefragt werden. Senden Sie Ihre Kommando.

9. Jetzt muß der Server noch um 3 Zeilen erweitert werden. Nehmen Sie vorhandene Beispiele als Vorlage.

Sie sehen, daß man für effiziente Client-Server Verbindungen nicht immer schwergewichtige Softwaremonster benötigt. Auch die Kombination eines C++ RAD Entwicklungswerkzeugs mit bewährten Netzwerk-Protokollen läßt ansprechende Programmierung zu. Ich hoffe Sie zu eigenen Lösungen angeregt zu haben. Wie wäre es mit einer Steuerung für den Unix Druckspooler ?

Fkaviar.cpp
...
15 TRegIniFile* Reg;
16 TfrmKaviar* frmKaviar;
17 DTcpClient cp;
18 DFieldDesc dfDesc;
19 DFieldDesc whoDesc;
20 DFieldDesc psDesc;
21 TStringList* LoginParam;
...
Reg ist das Objekt einer VCL Klasse für die einfache Verwendung der Windows Registry. In unserem Fall sorgt sie für die Speicherung der Verbindungsdaten und der letzten Fensterposition.

DTcpClient ist das Objekt für die Client Netzwerkverbindung.

DFieldDesc-Klassen enthalten die vom Server gesendeten Formatinformationen für die Datenströme der Kommandos. Je eine Instanz dieser Klasse wird für ps, who und df verwendet.

LoginParam, die Login-Parameter, bestehen aus 4 Strings (Host, User, Password, Programm), die in einem TStringList Objekt geführt werden.