Virtual OS/2 International Consumer Education
VOICE Homepage: http://de.os2voice.org
September 2003

[Inhaltsverzeichnis]
[Vorherige Seite] [Nächste Seite]
[Artikelverzeichnis]

editor@os2voice.org


Erstellung von Skripten zur Automation von Anwendungsmigrationen

Von Chris Clayton © September 2003, Übersetzung: Philhard Ackermann

Einleitung

In der Vergangenheit habe ich meine Rechner üblicherweise hoch gerüstet, indem ich anstelle einer Grundinstallation zu neueren Versionen migriert bin. Das Betriebssystem eines meiner Rechner ist seit 1993 tatsächlich das gleiche, abgesehen von OS/2-Neuerungen und FixPacks, und das, obwohl sich die Hardware seitdem etliche Male verändert hat. So war ich in der Lage, meine Arbeitsoberfläche über all die Jahre hinweg weitestgehend intakt zu erhalten.

Seit der Markteinführung der OS/2-Version 4.5 sowie der  eComStation (eCS) 1.0 ist dies deutlich schwieriger geworden. Nun, mit eCS 1.1 lautet die Empfehlung, eine Migration nicht einmal zu versuchen, sondern in jedem Fall eine Grundinstallation vorzunehmen. Daher habe ich mich, als Serenity Systems im Dezember 2002 eine Testversion von eCS 1.1 herausgab, dazu entschlossen, eine Grundinstallation durchzuführen und meine Anwendungen zu migrieren. Scheinbar hat sich das Hilfsprogramm 'Programme hinzufügen'  seit 1994 nicht verändert, denn es erkennt nur wenige der mehr als 60 Anwendungen, die ich verwende. Daher hat es, obwohl die Installation von eCS 1.1 sehr schnell ablief, fast zwei Tage gedauert, bis ich meine Arbeitsoberfläche wieder so hin bekommen hatte, wie sie mir gefällt.

Nachdem ich das einige Male gemacht hatte, fiel mir auf, daß ich dieselben Dinge immer wieder tat: Symbole umbenennen, Ordner verschieben und Objekte anpassen. Für mich bedeuten Vorgänge, die ich ständig wiederholen muß, daß man sie programmieren sollte. Zwar gibt es einige gute Werkzeuge, um den Zustand der Arbeitsoberfläche zu sichern und wiederherzustellen, aber der Aufbewahrungsort von Objekten hat sich mit eCS 1.1 drastisch verändert, und ich benötigte die Flexibilität zum Umgang mit den verschiedenen Konfigurationen, die ich einsetze. Meine Systeme  verwenden etliche Versionen von OS/2, von  Warp 4.0 bis eCS 1.1. Jedes System betreibt eine Menge von Anwendungen. Daher habe ich mir die Möglichkeiten der Programmiersprache REXX angesehen. Mit Hilfe der Möglichkeiten, die REXX bietet, habe ich drei REXX-Programme, die ich als Skripte bezeichne, sowie eine 4OS2-Batchdatei erstellt, um den Migrationsprozeß zu automatisieren. In diesem Artikel möchte ich darstellen, welche Werkzeuge man benötigt, wie man die REXX-Funktionen verwendet, die ich entwickelt habe, um eigene Skripte zu erstellen, und wie ich meine Skripte eingesetzt habe.

Voraussetzungen

Auch wenn die genannten Funktionen die Erstellung eigener Skripte stark vereinfachen, benötigt man grundlegende Kenntnisse der Programmiersprache REXX. Eine gute Basis, um damit zu beginnen, bietet die Broschüre "OS/2 Programmiersprache 2/REXX", die man mit der Basisinstallation von OS/2 oder eCS erhält. Verwenden Sie "Unterstützung" im SmartCenter oder führen sie folgenden Befehl im OS/2-Fenster aus: 

view REXX.INF
Zudem hat das VOICE-Magazin eine Artikelreihe von Thomas Klein zum Thema REXX-Programmierung veröffentlicht. Siehe den neuesten Artikel unter  http://www.os2voice.org/VNL/past_issues/VNL0703H/vnewsf2.htm.

Die "Workplace Shell Programming Reference" ist eine gute Quelle von Informationen zur Erstellung von WPS-Objekten. Früher einmal war dieses Buch auf der Internetseite von IBMs Developers Connection (s. http://service2.boulder.ibm.com/devcon) erhältlich, allerdings habe ich es dort in letzter Zeit nicht mehr finden können. Es wird zudem mit OS/2 Version 4.5x auf der Installations-CD im Verzeichnis \TOOLKIT\OS2TK45\BOOK, eComStation 1.0 (Deutsch) auf CD-Rom 1 in der Datei \DevToolKit\toolkit.zip, und eComStation 1.1 (Englisch) auf CD-Rom 3 im Verzeichnis \TOOLKIT\OS2TK45\BOOK verbreitet. Sie werden die Dateien wps1.inf, wps2.inf und wps3.inf nach d:\OS2\BOOK (wobei d:  das eCS-Startlaufwerk ist) kopieren oder extrahieren müssen, bevor Sie folgenden Befehl ausführen:

view wps1.inf+wps2.inf+wps3.inf
Zu guter Letzt werden Sie ein Werkzeug benötigen, das Ihnen die Eigenschaften von Objekten der Arbeitsoberfläche Workplace Shell (WPS)) sowie die Inhalte der Anwendungsinitialisierungsdateien (INI-Dateien) anzeigt. Ich habe hierzu des Programm  Unimaint verwendet. Hierbei handelt es sich um ein kommerzielles Programm mit einer grafischen Benutzeroberfläche, welches bei  BMT Micro erhältlich ist. Als Freeware-Programm wäre hier Henk Kelders WPTOOLS zu erwähnen. Dieses Werkzeug besteht aus einer Reihe von Einzelprogrammen und REXX-Skripten, die von der Befehlszeile aus aufgerufen werden. Die neueste Version ist als wptool29.zip bei Hobbes zu finden. Zu guter Letzt hat Mark Dodel erwähnt, daß  XWorkplace eine Option zur Anzeige von WPS-Informationen bieten soll. Seinen Aussagen zufolge findet man im Eigenschaften-Dialog eines Objektes unter dem Tabulator-Icon eine Schaltfläche Details. Ich konnte dies leider nicht verifizieren, weil ich XWorkplace nicht installiert habe.

Erstellung des Skripts

Um Ihnen zu verdeutlichen, wie ich diese Skripte erstellt habe, möchte ich ein Beispiel verwenden, welches Symantec  Antivirus migriert. Obwohl diese Anwendung der Allgemeinheit nicht ohne weiteres zugänglich ist (ich habe sie, weil mein Arbeitgeber sie vorschreibt und ausliefert), stellt sie dennoch ein gutes Beispiel dar, weil viele der Migrationsaktivitäten, um die Sie sich Gedanken machen müssen, durchgeführt werden. Ich werde hierbei Codeschnipsel  im Artikel verwenden; diese werden in einem Monospace-Zeichensatz dargestellt. Bei den REXX-Codezeilen habe ich versucht, die Länge unter 80 Zeichen zu halten. In einigen Fällen war dies nicht zu schaffen. Überschreitet die Länge einer Codezeile 80 Zeichen, dann ist der Teil, der in die nächste Zeile gebrochen werden mußte, zum ersten Teil der Anweisung passend eingerückt. Das komplette REXX-Beispielskript einschließlich meiner Funktionen, steht auf dem V.O.I.C.E.-Server zur Verfügung. <MigrSyma.cmd>

Einige Textprogramme fügen Formatierungsinformationen hinzu und speichern ASCII-Dateien unter Verwendung eines 'angereicherten Textformats' (Rich-Text-Format) ab, um diese Informationen zu erhalten, und könnten dort sogar 'unsichtbare' Kontrollzeichen einbringen. Solche Zeichen würden bei dem Versuch, Ihr Skript ablaufen zu lassen, zu Problemen führen. Überprüfen Sie die Einstellungen Ihres Textprogramms, um sicherzustellen, daß ASCII-Dateien auf jeden Fall ohne Formatierungsinformationen gespeichert werden. Wenn Sie sich des Verhaltens Ihres Textprogrammes hier nicht sicher sind, dann sollten Sie auf der sicheren Seite bleiben und den mit eCS gelieferten Text-Editor 'e.exe' verwenden, um Ihre Skripte zu erstellen oder zu modifizieren.

Der erste Schritt im Migrationsprozeß besteht darin, die an der WPS vorzunehmenden Änderungen zu ermitteln. Das ist der mühsame Teil. Das mindeste, was Sie herausfinden müssen, ist der Typ der Programmsitzung (z. B. OS/2-Programm-Manager [PM], DOS-Vollschirm [VDM], OS/2-Fenster [WINDOWABLEVIO], oder WINeCS-Vollschirm [WIN]), das verwendete auszuführende Programm sowie etwaige Parameter. Zusätzlich müssen Sie sich möglicherweise Symbolnamen, spezifische DOS-Einstellungen, Ordnerbezeichnungen und INI-Dateieinstellungen aufschreiben. Für das letztere benötigen Sie ein Werkzeug wie beispielsweise UniMaint, mit dem man INI-Dateien analysieren kann. Wenn Sie all diese Informationen beisammen haben, dann können Sie damit beginnen, Ihre Skripte zu erstellen. Um dies zu erleichtern habe ich einen Satz von Funktionen entwickelt, so daß die meisten Aktionen lediglich einen Funktionsaufruf erfordern, den man per Ausschneiden und Einfügen erstellen kann. Jede dieser Funktionen beinhaltet eine rudimentäre Fehlerprüfung, erstellt Logeintragungen über alles, was geschieht, und gibt einen Wert zurück, der entweder den Erfolg der Aktion anzeigt oder im weiteren Verlauf des Migrationsprozesses benötigt wird.

Zu Beginn der Skripte sind einige Initialisierungsschritte auszuführen. Der erste besteht aus einem Kommentar, der eCS mitteilt, daß es sich um ein REXX-Skript handelt.

/* Migrationsskript für Symantec Antivirus */
Danach sind einige globale Variablen zu definieren. Der erste Satz dieser Variablen besteht aus denen, die zur Anpassung durch den Anwender bestimmt sind. Diese beinhalten die zu erstellende Ordnerklasse. Normalerweise ist dies ein WPS-Ordner,  WpFolder, aber Sie könnten hier statt dessen auch eine andere Klasse, wie z. B. einen erweiterten Object-Desktop-Ordner, TSEnhFolder, verwenden, falls Sie Object Desktop installiert haben:
 clFolderClass = 'WpFolder'
Es ist besser festzuhalten, was so passiert, weil eine ganze Menge Dinge ziemlich schnell ablaufen, also muß ein Dateiname für eine Logdatei angegeben werden:
fLogFile = 'SymaMigr.log' /* Logdatei - ändern in '' falls nicht benötigt */
Außerdem muß man dem Skript mitteilen, wie Anpassungen an der config.sys vorgenommen werden sollen:
sCommitCgs = 'N'
/* 'Y' = config.sys verändern (die alte wird als config.mig gespeichert) */
/* 'N' = Änderungen in config.mig speichern (config.sys bleibt unverändert) */

Schließlich ist eine Initialisierungsdatei (INI) zu definieren, welche von der gegebenen Anwendung benutzt wird.  Im Fall von Symantec ist dies eigentlich die globale 'Anwender'-INI-Datei os2.ini, tatsächlich  aber verwenden wir zu Testzwecken eine eigene INI-Datei, die im aktuellen Verzeichnis angelegt wird.
 fDestINI = 'symatest.ini' /* USER */
Möglicherweise möchten Sie in Ihrem Skript einige weitere Variablen definieren. Beispielsweise:
 sIcons = 'E:\UTILITY\ICONS\'  /*  mein Verzeichnis für Symbole (Icons) */
Die nächste Kategorie globaler Variablen ist, ausgenommen wo dies ausdrücklich erwähnt ist, nicht zur Anpassung durch den Anwender vorgesehen, sondern wird benötigt, damit das Skript seine Arbeit machen kann.

Die erste beinhaltet den Aufbewahrungsort der Datei config.sys. Normalerweise ist dies das eCS-Startlaufwerk. Zu Testzwecken verwenden wir jedoch das aktuelle Verzeichnis, in welchem wir eine Kopie der config.sys anlegen:

/* Ermitteln des OS/2-Laufwerks (des Systemstartlaufwerks) */
sBootDrive = Substr(Translate(Value('PATH',,'OS2ENVIRONMENT')),Pos('\OS2\SYSTEM',Translate(Value('PATH',,'OS2ENVIRONMENT')))-2,2)
/* Fundort der config.sys - normalerweise sBootdrive, hier '.' zum Test */
sCfigDrive = '.' /* sBootDrive */
Wenn Sie Anpassungen an der config.sys beabsichtigen, dann sind die folgenden Variablen zu definieren (mehr darüber später):
/* Variablen zur Aufnahme von Zusätzen zur config.sys für: */
sNewBook = '' /* BOOKSHELF-Umgebungsvariable */
sNewDpath = '' /* DPATH-Umgebungsvariable */
sNewHelp = '' /* HELP-Umgebungsvariable */
sNewLib = '' /* LIBPATH-Anweisung */
sNewPath = '' /* PATH-Umgebungsvariable */

/* die folgende Verbundvariable dient zur Aufnahme zusätzlicher config.sys- */
/* Einträge */
stAddlCfg.0 = 0 /* die Erste enthält die Anzahl der Einträge */
/* .1 .. .n wird die eigentlichen Einträge enthalten */
Zu guter Letzt sind die REXX-Utility-Funktionen zu laden:
 Call RxFuncAdd 'SysLoadFuncs', 'REXXUTIL', 'SysLoadFuncs';
Call SysLoadFuncs;
Obwohl Sie ihre Anwendungen in jeden bereits existierenden WPS-Ordner migrieren können, ist es klüger, hierfür einen eigenen Ordner anzulegen. Für diese Aktion werden sie eine eindeutige Objektinformationsvariable (ID) sowie einen Titel und einen Ablageplatz definieren müssen. Um sicherzustellen, daß Objekt-IDs nicht mehrfach auftreten, lasse ich jede mit meinen Initialen gefolgt von einem Unterstrich beginnen: 'CMC_'. Das folgende Codesegment versucht einen Ordner mit dem Titel  'Mein Ordner' auf der Arbeitsoberfläche anzulegen. Ich sage versucht, weil es aufgrund des Systemdesigns versagen wird, falls ich keine eindeutige ID gewählt habe:
/* Anlegen eines Zielordners auf dem Desktop */
sFolder = '<CMC_MY_PROGS>'
sName = 'Mein Ordner'
rc = Message( 'Lege Desktop-Ordner an: '||sName )
rc = SysSetObjectData(sFolder,'' ) /* prüfen, ob Objekt existiert *
if RC = 1 THEN
DO
rc = Message( ' Ordner '||sName||' kann nicht angelegt werden, weil Objekt-ID '||sFolder||' bereits existiert' )
EXIT
END
ELSE
DO
sOptions = 'OBJECTID='||sFolder||';CONCURRENTVIEW=NO;'
sOptions = sOptions||'VIEWBUTTON=MINIMIZE;MINWIN=HIDE;'
sOptions = sOptions||'ICONVIEW=NONGRID,NORMAL;ICONVIEWPOS=25,10,50,70'
rc = SysCreateObject( clFolderClass, sName, '<WP_DESKTOP>', sOptions, 'fail' )
IF RC = 0 THEN
DO
rc = Message( ' Ordner '||sName||' kann nicht angelegt werden.' )
rc = Message( ' Sicherstellen, daß er gelöscht ist, und erneut versuchen.' )
EXIT
END
END /* sObject else */

Beachten Sie, daß die Routine Message dazu verwendet wird, den Fortschritt sowie das Resultat der Operationen darzustellen. Diese Routine schreibt sowohl Meldungen auf den Bildschirm als auch  Sätze in die definierte Logdatei. Dieses ausführliche Logging ist typisch für alle Funktionsaufrufe, die weiter unten beschrieben werden. Außerdem habe ich die ID  '<WP_DESKTOP>', die der Arbeitsoberfläche, verwendet, um anzuzeigen, wo der neue Ordner angelegt werden soll. Hierfür hätte ich auch jede andere gültige ID verwenden können. Um herauszufinden, welche ID einem Ordner zugeordnet ist, benötigen Sie das WPS-Analysewerkzeug.

Wenn Sie mehrere Anwendungen migrieren, dann empfielt es sich, verschiedene Unterordner in dem Hauptordner anzulegen, den Sie gerade erstellt haben. Um dies zu bewerkstelligen, habe ich eine Funktion namens CreateFolder erstellt, die diesen Prozeß vereinfacht:

sNewFolder = CreateFolder( sDestination, sTitle, sObjectID )
wobei sDestination den Zielort der Ordnererstellung, sTitle den Objekttitel sowie sObjectID die eindeutige Objekt-ID enthält. Der hauptsächliche Unterschied zwischen dieser Funktion und dem Codeschnipsel weiter oben besteht darin, daß die Funktion das Skript nicht abbricht, falls Probleme auftreten. Statt dessen wird, falls die Operation erfolgreich war, die ID des neuen Ordners zurückgegeben und, falls nicht erfolgreich, die ID des Zielordners. In meinem Beispiel zur Migration von Symantec wird ein Utility-Ordner innerhalb des Hauptordners 'Mein Ordner' (sFolder) angelegt:
sUtility = CreateFolder( sFolder, 'Utility', '<CMC_MY_UTIL>' )
Nun ist es an der Zeit, die Objekte für die Anwendungen anzulegen, die Sie zu migrieren wünschen. Auch hierfür habe ich eine Funktion,  CreateApp, erstellt, die diese Operation sehr einfach macht:
rc = CreateApp( sDestination sTitle, fExe, sObjectID, sProgType, sExtras )
wobei sDestination der Ordner ist, in dem das Objekt erstellt werden soll, sTtile den Objekttitel,  fExe den Namen der ausführbaren Datei einschließlich komplettem Pfad,  sObjectID die eindeutige Programmobjekt-ID,  sProgType den Sitzungstyp des Programms sowie sExtras eine Zeichenkette mit zusätzlichen Objektparametern enthält. Den Sitzungstyp haben wir weiter oben während der Phase besprochen, in der wir die Programminformationen zusammengetragen haben. sExtras wird üblicherweise zur Parameterübergabe eingesetzt:
sExtras = 'PARAMETERS=....;'
Allerdings kann diese Variable für weit mehr verwendet werden, wie z. B. zur Angabe  von DOS-Sitzungsvariablen. Außerdem stehen, zusätzlich zu den oben genannten, noch einige weitere Sitzungstypen zur Verfügung. Um mehr über diese herauszufinden schauen Sie bitte in der "OS/2 Warp Workplace Shell Programming Reference" nach.

Im Beispielskript migrieren wir mehrere Anwendungen auf einmal. Die erste ist ein einfaches WPS-Programm, welches keinerlei zusätzliche Parameter zur Objekterstellung benötigt. Daher wird  sExtras auf einen Null-String, '', gesetzt:

rc = CreateApp( sUtility, sName, fFile, '<CMC_AV_PROG>', 'PM', '' )
Die zweite ist ein Programm, welches in einem OS/2-Fenster anläuft, und zusätzlich zu den Parametern wird ein Programmsymbol (Icon) angegeben:
sParms = 'PARAMETERS=a:\*.* /doallfiles /repair /s+;ICONFILE='||sIcons||'VIRUS.ICO'
rc = CreateApp( sUtility, 'Scanne a:', 'E:\SYMANTEC\NAVDXOS2.EXE', '<CMC_AV_SCANA>', 'WINDOWABLEVIO', sParms )
Beachten Sie, daß bei Verwendung mehrerer Zeichenketten zur Angabe zusätzlicher Objektparameter ein ';' als Trennzeichen erwartet wird. Zur Vorsicht ein Hinweis: die Funktion CreateApp geht von einigen Standardannahmen aus. Eine dieser Standardannahmen besteht darin, daß das Arbeitsverzeichnis einer Anwendung immer dem Pfad des aufgerufenen Programms entspricht. Sollten diese Standardannahmen nicht dem entsprechen, was Sie benötigen, dann müssen Sie nach dem Anlegen des Objektes die REXX-Utilityfunktion SysSetObjectData aufrufen. Beispiel:
rc = SysSetObjectData( '<CMC_AV_SCANA>', 'STARTUPDIR=E:\SYMANTEC' )
Einige Programme benötigen Anpassungen an Pfaddefinitionen und anderen config.sys-Einträgen. Für solche Änderungen habe ich drei Funktionen erstellt. Die ersten beiden, ConcactPath und AddCfgEntry, werden im gesamten Skript an den verschiedensten Stellen verwendet, um die Änderungen festzuhalten, bis am Ende des Skripts die Funktion UpdateConfigSys aufgerufen wird, um sie letzlich festzuschreiben.

ConcactPath dient dazu, der zugehörigen Pfad-Variablen der config.sys ein Verzeichnis hinzuzufügen. Zuerst prüft sie, ob das angegebene Verzeichnis existiert, und produziert eine Warnmeldung, falls es nicht vorhanden ist. Anschließend wird das Verzeichnis mit korrektem Trennzeichen an das Ende der existierenden Pfad-Definition angehängt. Abhängig davon, welchem  Umgebungspfad (BOOKSHELF, DPATH, HELP, LIBPATH oder PATH) etwas hinzugefügt werden soll, ist die zugehörige globale Variable an ConcactPath zu übergeben bzw. wird von der Funktion gefüllt: sNewBook, sNewDpath, sNewHelp, sNewLib, oder sNewPath. Diese Variablen wurden bei der Initialisierung des Skriptes weiter oben auf einen Null-String gesetzt.  Im Beispielskript ist folgender Aufruf von ConcactPath enthalten:

sNewLib = ConcactPath( sNewLib, 'E:\SYMANTEC', 'LIBPATH' )
Hier soll LIBPATH verändert werden, daher wird sNewLib als erster Parameter übergeben. Der zweite Parameter ist das Verzeichnis, das hinzugefügt werden soll, und der dritte wird verwendet, um die zu verändernde config.sys-Variable für Zwecke des Mitloggens zu identifizieren. Das Resultat der Funktion wird in  sNewLib abgelegt.

AddCfgEntry ermöglichst es Ihnen, der config.sys-Zeilen hinzuzufügen. Um dies zu bewerkstelligen wird eine REXX-Stammvariable, enables you to add entire lines to config.sys. To do this it uses a REXX stem variable, stAddlCfg., verwendet, um die Änderungen zwischenzuspeichern, bis sie der config.sys tatsächlich hinzugefügt werden. Eine Stammvariable entspricht in etwa einer Tabellenvariablen in anderen Programmiersprachen. Im vorliegenden Fall enthält das erste Tabellenelement,  stAddlCfg.0, die Anzahl der hinzuzufügenden Zeilen. Der Rest der Tabelle,  stAddlCfg.n, beinhaltet die eigentlichen Zeilen. Im folgenden Beispiel wird eine Kommentarzeile gefolgt von einer Anweisung zum Setzen einer Umgebungsvariablen hinzugefügt:

rc = AddCfgEntry( 'REM Symantec Antivirus' )
rc = AddCfgEntry( 'SET SYMANTEC=E:\SYMANTEC' )
Diese Funktion kann auch dazu verwendet werden, von einer Anwendung etwa benötigte Treiber hinzuzufügen.

Am Ende des Sripts wird UpdateConfigSys aufgerufen, um die Änderungen an der config.sys festzuschreiben:

IF bOK = 'TRUE' THEN rc = UpdateConfigSys( sCommitCgs )
exit bOK \= 'TRUE'
Die Variable sCommitCgs ist während der Initialisierung des Skripts definiert worden und dient der Festlegung, wo config.sys-Änderungen festgehalten werden: in der config.sys selbst oder in einer Alternativdatei, config.mig.

Die Funktion UpdateConfigSys nimmt alle Änderungen vor, indem sie die config.sys zunächst untersucht und Pfadumgebungsvariablen verändert, wenn sie die passenden Variablen gefunden hat. Die Funktion prüft zudem, ob die angestrebten Zusätze bereits eingetragen sind. Falls dem so ist, werden die vorhandenen Einträge weiterverwendet. Allerdings ist diese Prüfung recht simpel, denn es wird nur die komplette Zeichenkette gesucht, genauso wie sie übergeben wurde. Es ist sicherlich möglich, jeden Verzeichniseintrag einzeln zu prüfen. Das wird zwar etwas chaotisch, ist aber nicht allzu schwer zu kodieren, deshalb übergebe ich es als Übungsaufgabe an meine Leser. Als Seiteneffekt, da die Funktion ohnehin bereits die config.sys durchkämmt, hat man hier eine ausgezeichnete Gelegenheit, Veränderungen an bereits vorhandenen config.sys-Einträgen, wie Treiberparametern, vorzunehmen. Das Skript zur Migration von Symantec enthält einige Beispiele für diesen Vorgang. 

Nachdem die config.sys durchsucht wurde, werden die Zeilen, die sich in der Stammvariablen stAddlCfg befinden, hinzugefügt. Da es keinerlei Möglichkeit gibt, zu überprüfen, ob die Syntax der neuen Zeilen korrekt ist, wird hier keine Fehlerprüfung vorgenommen. Zur Sicherheit machen Sie sich am besten eine Kopie der Original-config.sys, selbst wenn  Sie sich dazu entscheiden, die Veränderungen in einer alternativen Datei abzuspeichern.

Bei einigen Programmen ist es zum Zwecke einer funktionierenden Migration unabdingbar, entweder eine INI-Datei zu erstellen oder eine existierende INI-Datei, wie die Anwender-INI-Datei os2.ini, zu modifizieren. Sollte es tatsächlich nötig sein, daß Sie eine INI-Datei verändern, dann machen Sie sich auf jeden Fall eine Sicherheitskopie davon, bevor Sie weitere Schritte ausführen. Die Funktion CreateINIentry vereinfacht das Hinzufügen von Einträgen von INI-Dateien:

rc = CreateINIentry( fDestINI, 'SymantecInstalledApps', 'AVENGEDEFS', sDefsDir, 'Y' )
wobei fDestINI die zu verändernde INI-Datei angibt. Dies kann entweder der Name einer Datei sein, welche angelegt wird, falls sie noch nicht existiert, 'USER' für die Anwender-INI-Datei, 'SYSTEM' für die System-INI-Datei, os2ini.sys, oder 'BOTH'. Das Letztgenannte durchsucht sowohl die System- als auch die Anwender-INI-Datei, verändert aber nur die Anwender-INI-Datei. Der nächste Parameter bezeichnet den Namen der hinzuzufügenden  Anwendung, der zweite den Namen des mit der Anwendung assoziierten Schlüssels sowie der vierte den Wert dieses speziellen Schlüssels. Der letzte Parameter ist 'Y' oder 'N', um anzugeben, ob der angegebene Schlüsselwert mit einem Nullterminator versehen werden soll. Dieser Parameter wird deshalb benötigt, weil REXX-Zeichenketten keinen Nullterminator verwenden, viele INI-Einträge aber sehr wohl. Der Rückgabewert von CreateINIentry ist das Resultat der Operation: eine Nullzeichenkette '', falls der Wert erfolgreich hinzugefügt werden konnte, der Wert eines existierenden Eintrags oder 'ERROR:' falls irgend etwas schiefgegangen ist. Da wir hier versuchen, eine INI-Datei zu verändern, die von eCS selbst verändert wird, führt die Funktion umfangreiche Fehlerprüfungen durch, bevor sie irgendwelche Veränderungen vornimmt. Die erste dient dazu, herauszufinden, ob die angegebene Anwendung sowie der Schlüssel bereits existieren. In diesem Fall wird der Wert des existierenden Schlüssels zurückgegeben und im Log vermerkt und keine Änderungen vorgenommen. Als nächstes wird der Versuch, einen neuen Schlüssel anzulegen, im Log festgehalten. Bitte beachten Sie, daß die Funktion überwiegend dazu eingesetzt wird, Schlüsselwerte hinzuzufügen, die in Textform vorliegen. Manche Programme verwenden Schlüsselwerte im Binärformat. Obwohl diese Funktion solche Fälle abhandeln kann,  können solche Einträge recht lang und schwierig zu implementieren sein. In einem solchen Fall schlage ich vor, daß Sie davon ausgehen, daß die Anwendung sorgfältig entwickelt wurde und Standardannahmen machen kann. Versuchen Sie zunächst, den Binärwert wegzulassen, und prüfen Sie, ob die Anwendung dennoch läuft. Läuft sie nicht, dann fügen Sie die Anwendung einen Schlüssel mit einem Nullwert, also dem Nullstring, sowie einem 'Y' zum Anhängen eines Nullterminators hinzu. Wenn das auch nicht läuft, dann liegt Ihnen eine Anwendung vor, die nicht sauber programmiert ist und die Sie neu installieren müssen. 

Dies schließt die Aktivitäten, die ich unternommen habe, um Anwendungen automatisch zu migrieren. Dennoch gibt es noch einen zusätzlichen Schritt, den einige Anwendungen benötigen könnten - die Registrierung von dynamischen Linkbibliotheken (DLL) bei eCS. Dies ist unter Verwendung der REXX-Utilityfunktion SysRegisterObjectClass( classname, modulename) nicht allzu schwierig. Der Trick dabei ist, die Werte der Funktionsparameter herauszufinden. Dies kann leicht bewerkstelligt werden, indem man untersucht, welche DLLs vor der eCS-Neuinstallation beim System angemeldet waren. UniMaint ist in der Lage, diese Information zu ermitteln, andererseits beinhaltet REXX eine Funktion SysQueryClassList, welche eine Stammvariable mit den Objekten füllt, die derzeit registriert sind. Um weitere Informationen zu erlangen, konsultieren Sie bitte  das Handbuch über die Prozedursprache REXX, welches mit OS/2 und eCS  ausgeliefert wird.

Ich möchte Ihnen einige zusätzliche Funktionen zur Verfügung stellen, die zwar im Script zur Migration von Symantec nicht zum Tragen kommen und bisher auch noch nicht erwähnt wurden, in einem meiner anderen Migrationsskripte  jedoch verwendet werden. Dies sind die Funktionen ConcactTabID, MoveObject und ShadowObject. Die erste Funktion dient dazu, der Object Desktop Tab Launchbar automatisch Objekte hinzuzufügen:

sDest = ConcactTabID( sDest, iTab, sObjID, sPlace )
Diese Funktion wird auf ähnliche Weise verwendet wie diejenige, die den Pfaden Verzeichnisse hinzufügt.  sDest ist die Zeichenkette, die zum Speichern der hinzuzufügenden Objekt-IDs dient. Sie wird der Funktion sowohl übergeben als auch von ihr mit einem Rückgabewert gefüllt. iTab ist die Nummer des Tabulators, dem etwas hinzugefügt werden soll. sObjectID ist die eindeutige Objekt-ID, die hinzuzufügen ist, und sPlace ist der Name des hinzuzufügenden Objekts und dient dem Mitloggen des Vorgangs. Wie bei den Pfadumgebungsvariablen wird die Funktion dazu verwendet, die neuen Einträge der Tab Launchbar additions solange zu kumulieren, bis sie irgendwann durch einen Aufruf von SysSetObjectData festgeschrieben werden:
rc = SysSetObjectData('<OBJD_TABLAUNCHPAD>', 'ADDOBJECTS='||sDest )
Es mag möglich sein, eine ähnliche Routine zu entwickeln, die dem eCenter Fächer und Objekte hinzufügt. Der Trick dabei ist, die richtigen Eigenschaften oder Objekte herauszubekommen, die angepaßt werden müssen.  Möglicherweise könnten die Autoren des eCenters ja einen Artikel darüber veröffentlichen, welche Parameter zur Objektmanipulation sie definiert haben. Solche wie zum Hinzufügen und Entfernen von Symbolen (Icons) zu einem speziellen Fach.  

Eine weitere der zusätzlich zur Verfügung gestellten Funktionen dient dazu, Objekte von einem Ordner in einen anderen zu verschieben:

sResult = MoveObject( sSource, sDest, sName )
sSource und sDest sind Objekt-IDs für das zu bewegende Objekt sowie seinen Zielort. sName ist erneut eine Objektbeschreibung, die zum Mitloggen des Vorgangs dient. Die Funktion prüft, ob das zu bewegende Objekt tatsächlich existiert. Anschließend gibt die Funktion ein Ergebnis der Operation als Wert zurück. Sollte sie versagen, dann stellen Sie sicher, daß das Zielobjekt ein existierender Ordner ist. Die dritte Funktion erstellt eine Referenz eines Objektes in einem Ordner:
sResult = ShadowObject( sSource, sDest, sName )
Die Parameter entsprechen denen von MoveObject. Durch die Verwendung dieser Funktionen in meinen Skripten bin ich in der Lage, meiner Arbeitsoberfläche recht schnell den letzten Schliff zu verpassen.

Beispiel

Als Beispiel möchte ich detailiert beschreiben, wie ich meine Skripte verwende. Meine eCS-Installation wird in vier Schritten vorgenommen. Der erste Schritt ist natürlich die Grundinstallation von eCS. Ich verwende die Installation für Fortgeschrittene (advanced installation method), weil man dort die zu installierenden Features und die Netzwerkinstallation den eigenen Bedürfnissen anpassen kann. Nach Abschluß der Installationsphase 4 erstelle ich unverzüglich ein Archiv. Mir ist bekannt, daß eCS nach der Installation automatisch eine Archivierung vornimmt, aber viele der finalen Aktivitäten werden nicht mitgesichert. Da die von mir erstellten Skripte die Arbeitsoberfläche (WPS) verändern, ist es essentiell, einen sauberen Aufsetzpunkt zu haben, falls etwas schiefgeht. Als Nebeneffekt ist es unabdingbar, sicherzustellen, daß das angeforderte Archiv auch tatsächlich erstellt wurde. Mir ist aufgefallen, daß die erste Anforderung zur Erstellung eines Archivs bisweilen ignoriert wird. Um sicher zu sein, überprüfen Sie die Inhalte von d:\OS2\BOOT\ALTF1MID.SCR. Wenn der oberste Eintrag nicht Zeit- und Datumsstempel des letzten Systemneustarts aufweist, dann starten Sie das System unverzüglich erneut durch und versichern Sie sich, daß ein Archiv erstellt wurde. Anschließend können Sie mit dem Migrationsprozeß forfahren.

Im zweiten Schritt meines Migrationsprozesses rufe ich ein Skript auf, das etliche Treiber und Konfigurationsdateien zum Installationslaufwerk kopiert, die config.sys zur Ausführung späterer Schritte präpariert sowie ein 4OS2-Objekt auf der Arbeitsoberfläche erstellt. Die Verwendung von 4OS2 (einem Austauschbefehlsprozessor für OS/2) ist keine Voraussetzung für die Durchführung der Migration, es macht die Sache nur ein wenig bequemer. Danach erfolgt die Installation von Treibern. Wenn alles zu meiner Zufriedenheit abgeschlossen ist, archiviere ich meine Arbeitsoberfläche erneut. Im dritten Schritt findet die Hauptarbeit der Migration statt. Ich beginne mit einem Skript zur Migration von WPS-Erweiterungen wie Ctrl-Alt-Del-Commander und Object Desktop sowie Anwendungen, die ein Programm zum erneuten Anlegen ihrer Objekte mitbringen. Anschließend modifiziere ich die Initialisierungsdatei des Programmanagers von WINeCS, PROGMAN.INI, um die diversen WINeCS-Gruppen aufzunehmen, die ich in Schritt 2 kopiert habe. Danach lasse ich 'Programme hinzufügen' laufen, um diese Gruppen sowie andere WINeCS-Anwendungen zu migrieren, die sich in der Datenbank  befinden. Einige Programme lassen sich unter Verwendung der Installationsdatenträger recht einfach migrieren, daher lasse ich dies als nächstes ablaufen. Danach führe ich ein Skript aus, welches den größten Teil meiner Anwendungen, insgesamt 40, migriert. Erneut erstelle ich ein Archiv. Als letzten Schritt rufe ich ein Skript auf, welches Ordner und Programmobjekte verschiebt sowie Referenzen der von mir öfter verwendeten Objekte auf der Arbeitsoberfläche erstellt. Nun noch einige wenige Nacharbeiten von Hand, und ich bin fertig. Zeitbedarf für den kompletten Vorgang: weniger als zwei Stunden!

Zusammenfassung

Ich habe einige Funktionen sowie ein Beispielskript zur Verfügung gestellt, welches den Migrationsprozeß bei der Neuinstallation eines OS/2- oder eCS-Systems, welches Anwendungen enthält, automatisiert. Diese Funktionen wurden in einer Art geschrieben, daß sie einfach mittels Ausschneiden und Einfügen genutzt werden können, und das Erstellen von Ordnern, das Anlegen von Anwendungsobjekten, Veränderungen an der config.sys sowie die Erstellung von Einträgen in INI-Dateien abdecken. Zur Erinnerung: ich möchte Ihnen ausdrücklich ans Herz legen, daß sie regelmäßige Sicherungen Ihrer Systemdateien und Archive während dieses Migrationsprozesses vornehmen. Ich hoffe, daß diese Funktionen Ihre Migration zu eCS 1.1 sowie späteren Versionen beschleunigen werden.

Daten und Quellen:

"OS/2 Procedures Language 2/REXX manual", International Business Machines (1997).
OS/2 Warp Version 4 Technical Library, "Workplace Shell Programming Reference," International Business Machines, (November, 1996).
Beispielmigrationsskript für Symantec Antivirus - http://www.os2voice.org/VNL/past_issues/VNL0903H/MigrSyma.cmd
Weitere Verweise:
    Unimaint einschlieálich Handbüchern verfügbar bei BMT Micro für $80.00 US ($65.00 ohne Handbücher) - http://www.bmtmicro.com/BMTCatalog/os2/unimaint.html
    WPTOOLS verfügbar bei Hobbes - http://hobbes.nmsu.edu/cgi-bin/h-search?key=wptool


[Artikelverzeichnis]
editor@os2voice.org
[Vorherige Seite] [Inhaltsverzeichnis] [Nächste Seite]
VOICE Homepage: http://de.os2voice.org