FoxIs, ein Visual FoxPro-Internetserver
Anhand des Beispielprojekts FoxIs, das sich im Visual FoxPro-Verzeichnis …\Samples\Servers\Foxisapi\FoxIs befindet, wird die Erstellung eines prozessexternen EXE- oder eines prozessinternen DLL-Servers mit ISAPI-Funktionalität veranschaulicht, auf den von Visual FoxPro aus als eigenständiges Programm, von Automatisierungsclients und von einem Webbrowser aus zugegriffen werden kann. Änderungen, die Sie an seinen Klassen vornehmen, können den Automatisierungsserver erweitern, unabhängig davon, wie er ausgeführt wird.
So öffnen Sie das Beispielprojekt FoxIs
Geben Sie die folgenden Anweisungen in das Befehlsfenster ein:
MODIFY PROJECT (HOME(2) + 'servers\foxisapi\foxis\foxis')
Ausführen des FoxIs-Beispiels
Sie können das FoxIs-Beispiel auf vier verschiedene Arten ausführen. Wenn Sie den Code ausprobieren, ist es sinnvoll, das Beispiel in der folgenden Reihenfolge auszuführen:
Ausführen aus Visual FoxPro heraus
Um das FoxIs-Beispiel aus Visual FoxPro heraus auszuführen, führen Sie den folgenden Code im Befehlsfenster aus:
SET DEFAULT TO (HOME(2) + 'servers\foxisapi\foxis\')
SET CLASSLIB TO employee
ox = CREATEOBJECT('employee')
ox.show
Ausführen als unabhängige ausführbare Datei
Sie können das Beispiel mit der folgenden Codezeile als ausführbare Datei erstellen:
BUILD EXE foxis FROM foxis
Die kompilierte Datei FOXIS.EXE ist ein Windows-Programm, das dem Startmenü von Windows hinzugefügt werden kann, von Windows-Explorer aus gestartet werden kann usw.
Ausführen als Automatisierungsserver
Sobald das FoxIs-Beispiel als eine EXE- oder DLL-Datei kompiliert wurde, ist es als Automatisierungsserver in der Windows-Registrierung registriert. Sie können aus jedem OLE-Controller, wie z. B. Excel, Visual Basic und Visual FoxPro, ein Objekt erstellen, das auf der Employee-Klasse basiert.
ox = CREATEOBJECT('foxis.employee')
ox.SHOW
Ausführen aus einem Webbrowser heraus
Sie können das FoxIs-Beispiel sogar aus einem Webbrowser ausführen, der sich auf einem anderen Computer befinden kann, z. B. einem 286er, der unter MS-DOS ausgeführt wird, einer UNIX-Maschine, einem Macintosh oder einem PDA (Persönlicher Digitaler Assistent).
Systemanforderungen für Internetanwendung
Um das FoxIs-Beispiel aus einem Webbrowser auszuführen, müssen Sie mit folgender Software arbeiten:
- Windows 98 oder Windows NT, Version 4.0 oder höher.
- Ein ISAPI-kompatibler Webserver, z. B. Microsoft Personal Web Server für Windows 98 oder Microsoft Internet Information Server (IIS). IIS ist im Lieferumfang von Windows NT, Version 4.0 und höher, enthalten und kann von www.microsoft.com gedownloadet werden. Hier wird auch Personal Web Server zum Downloaden zur Verfügung gestellt.
Wenn Sie Windows NT, Version 4.0 oder höher, verwenden, müssen Sie das Dienstprogramm DCOMCNFG ausführen, um DCOM so zu konfigurieren, dass der IIS-Dienst das Recht zur Instanziierung von OLE-Objekten erhält.
So konfigurieren Sie DCOM für Windows NT, Version 4.0 oder höher
Geben Sie an der Eingabeaufforderung DCOMCNFG ein, und drücken Sie die EINGABETASTE.
Wählen Sie den Namen des Automatisierungsservers auf der Registerkarte Anwendungen aus. Wenn Sie den Server erstellen, ist die Anwendung standardmäßig "employee".
Wählen Sie im Dialogfeld Eigenschaftenvon DCOM-Konfiguration auf der Registerkarte Standardsicherheit für jeden Bereich (Standard-Zugriffsberechtigungen, Standard-Startberechtigungen und Standard-Konfigurationsberechtigungen) die Schaltfläche Standard ändern.
Wählen Sie im Dialogfeld Registrierungswertberechtigungen für jeden Bereich Hinzufügen.
Geben Sie den Namen des WWW-Servers und Ihren Anmeldebenutzernamen im Feld Namenhinzufügen des Dialogfeldes BenutzerundGruppen hinzufügen ein.
Der Name des Servers wird im Fenster Eigenschaften des Microsoft Internet Service Managers angezeigt. Wenn der Name des Computers MINE lautet, wird durch die folgende Zeile im Feld Namenhinzufügen ein Standardbenutzer eingerichtet.
\MINE\IUSR_MINE
Wenn der Name des Computers MINE lautet und Sie sich als HOMER anmelden, werden durch die folgende Zeile im Feld Namenhinzufügen Berechtigungen für Sie eingerichtet, wenn Sie sich anmelden.
\MINE\HOMER
Einrichten des FoxIs-Beispiels für Internetzugriff
Um das FoxIs-Beispiel einzurichten, müssen Sie eine EXE- oder DLL-Datei aus dem FoxIs-Projekt heraus erzeugen und dann die Datei in das Verzeichnis Inetsvr\Scripts kopieren.
So richten Sie ein FoxIs-Beispiel ein
- Öffnen Sie das Projekt FoxIs.
- Wählen Sie die Schaltfläche Erstellen, und aktivieren Sie dann die Option Single-Thread-COM-Server (DLL).
- Kopieren Sie Foxisapi.dll in den Ordner Inetsrv\Scripts.
Einleitendes Testen
Sie können die FoxIs-Beispielanwendung auf verschiedenen Ebenen testen, um zu überprüfen, ob sie richtig konfiguriert ist.
So überprüfen Sie, ob der Code funktioniert
- Wählen Sie aus dem Menü Programm den Befehl Ausführen.
- Wählen Sie Main.prg im Visual FoxPro-Ordner Samples\Servers\Foxisapi aus.
- Wählen Sie Ausführen.
So überprüfen Sie, ob die EXE funktioniert
Geben Sie folgenden Befehl im Visual FoxPro-Befehlsfenster ein:
BUILD EXE Foxis.exe FROM foxis
Doppelklicken Sie in Windows Explorer auf Foxis.exe.
So überprüfen Sie, ob der FoxIs-Automatisierungsserver funktioniert
Führen Sie die folgenden Befehle aus:
OX= CREATEOBJECT('FOXIS.EMPLOYEE') OX.Show && See if it works as a ISAPI Automation server ?OX.Startup( ) && See if it returns html
Es ist wesentlich einfacher, einen Automatisierungsserver aus einem Automatisierungscontroller (z. B. Visual FoxPro) zu debuggen, bevor er in FoxIs instanziiert wird.
Einrichten der HTML-Seite
Zu Anfang benötigen Sie eine HTML-Seite, die einen Verweis auf einen URL enthält. Nehmen Sie beispielsweise den folgenden Code, und fügen Sie ihn in die Datei Wwwroot\default.htm ein.
<a HREF="/scripts/foxisapi.dll/FoxIS.employee.startup"> <i>VFP ISAPI AUTOMATION SERVER DEMO PAGE</i> </a>
Verwenden Sie dann einen Browser (der sich auf demselben Computer befinden kann), und verbinden Sie ihn mit NameIhrerMaschine. Wenn der Name des Computers z. B. MeinComputer lautet, müssen Sie MeinComputer als aufzurufenden URL eingeben. Hierdurch wird die Seite Default.htm auf dem Server mit dem Namen MeinComputer geöffnet.
Ein Employee-Objekt wird mit CreateObject("foxis.employee") instanziiert und die Startup-Methode auf das Objekt angewendet, welches die erzeugte HTML-Seite zurückgibt. Wenn der ISAPI-Automatisierungsserver noch nicht erzeugt wurde, gibt Foxisapi.dll eine HTML-Fehlerseite zurück.
Verwenden Sie dann den Webbrowser, um die oben genannte href aufzurufen. Wenn eine HTML-Fehlerseite mit der Meldung "Foxisapi-Fehler" angezeigt wird, wissen Sie, dass die DLL geladen wird und funktioniert.
<FORM ACTION = "/scripts/foxisapi.dll/foxis.employee.cmd">
<INPUT NAME="Cmd" VALUE = "Reset">
<INPUT TYPE="submit" VALUE="Dos Command">
</FORM>
Sie können jeden gültigen MS-DOS-Befehl eingeben; dieser wird dann auf dem Servercomputer ausgeführt. Wenn der Befehl Reset (Standardeinstellung) lautet, wird er den ISAPI-Automatisierungsserver veranlassen, die erste Instanz ebenso wie die eigene freizugeben und so den ISAPI-Automatisierungsserver vollständig zu löschen.
Zusätzlich können Sie einen Visual FoxPro-Ausdruck auswerten. Wenn der Visual FoxPro-Ausdruck jedoch eine modale Schnittstelle anzeigt, wie beispielsweise die MESSAGEBOX( )-Funktion, wartet der Automatisierungsserver in einer Warteschleife auf eine Antwort, die nicht gegeben werden kann. Für eine prozessinterne DLL wird die modale Schnittstelle jedoch automatisch verwaltet, und der Automatisierungsserver gelangt nicht in eine Warteschleife.
<FORM ACTION = "/scripts/foxisapi.dll/foxis.employee.cmd?FOXCMD">
<INPUT NAME="Cmd">
<INPUT TYPE="submit" VALUE="Fox Expression">
like "today is "+ cdow(date()) or 45 * 3 or SYS(2004)
</FORM>
Debuggen des Servers
Ein Windows NT-Dienst besitzt keine Oberfläche, daher wird auf dem Servercomputer keine Benutzeroberfläche angezeigt. Dies bedeutet, dass Sie Ihre Serveranwendungen debuggen müssen, bevor sie bereitgestellt werden.
So verfolgen Sie durch "Foxisapi.dll" mit Visual C++ 5.0
Öffnen Sie Foxisapi.mak.
Entfernen Sie die Kommentarmarke in der folgenden Zeile in HttpExtensionProc:
// _asm int 3
Erstellen Sie das Projekt neu.
Starten Sie MSDEV mit der Prozess-ID (PID) von Inetinfo.exe. Die Prozess-ID wird im Task-Manager von Windows angezeigt.
Dieser Vorgang betrifft Windows NT, Version 4.0 oder höher.
Tipp Sie brauchen während des Debuggens den Webserver nicht herunterzufahren, um den Automatisierungsserver zu wechseln. Sie können die prozessexterne Komponente beenden, indem Sie, wie oben beschrieben, einfach einen Zurücksetzungswert an die cmd-Methode senden oder die Win32 SDK-Tools TLIST, KILL, PVIEW oder den Task-Manager von Windows NT, Version 4.0 oder höher, verwenden.
Die "ISForm"-Klasse
Das "Modul" des Beispiels ist die ISForm-Klasse in Isapi.vcx.
Einsprungpunkte in die "ISForm"-Klasse
Die folgenden Methoden können vom Webbrowser über Foxisapi.dll aufgerufen werden, um HTML-Seiten zurückzugeben.
Methode | Rückgabetypen |
---|---|
Cmd | Auswerten eines Visual FoxPro-Ausdrucks oder des Ergebnisses eines MS-DOS-Befehls |
DoSave | Speichert die Änderungen des Benutzers an den Daten und gibt die HTML-Seite employee zurück. |
Skipit | Die Angestellteninformationen für den angegebenen Angestellten in der Tabelle. Skipit nimmt Cookieinformationen entgegen, die vom Webbrowser als Parameter übergeben werden, überprüft die Cookietabelle, um die Nummer des vorangegangenen Datensatzes zu finden, und bewegt den Datensatzzeiger vorwärts oder rückwärts, entsprechend den in der Cookietabelle gespeicherten Datensatznummern. Die neue Datensatznummer wird in die Cookietabelle zurückgeschrieben und die GenHTML-Methode aufgerufen. |
Startup | Die Angestellteninformationen für den ersten Angestellten in der Tabelle. Startup erzeugt eine neue Cookienummer für den Benutzer und sendet diese als verborgenen Eingabebereich im HTML-Code zurück. |
Aktivhalten des Servers
Normalerweise wird der Automatisierungsserver für jede Anforderung von einem Webclient instanziiert; er generiert eine HTML-Seite und wird mit dem Release( )-Aufruf in CallObject( ) in Foxsapi.cpp freigegeben. Dies bedeutet, dass die gesamte Visual FoxPro-Laufzeitumgebung für jede Anforderung geöffnet und geschlossen wird.
Wenn der benutzerdefinierte ISAPI-Automatisierungsserver für die mehrfache Verwendung registriert ist und Release( ) nicht aufgerufen wird, startet die erste Anforderung den Server. Nachfolgende Anforderungen werden jedoch dieselbe Instanz des Servers verwenden und so das Leistungsverhalten erheblich verbessern. Code in Foxisapi.dll und in den Methoden Load, Cmd, DoSave, Startup und Skipit von ISForm verwaltet das Aktivhalten des Servers in derselben Instanz.
Variablen in der DLL
Zwei Variablen werden deklariert: pdispObj und pdispDoRelease. Wenn der Server erstmalig erzeugt wird, ist pdispObj das Dispatchhandle für das OLE-Objekt. Die Variable pdispDoRelease wird auf denselben Wert festgelegt wie pdispObj und als Verweis als ein Parameter an die Methode des ISForm-Servers übergeben, die vom Webserver angefordert wurde. Code im Visual FoxPro ISForm Automatisierungsserver kann den Wert von pdispDoRelease ändern.
Tipp Weitere Informationen zu diesem Beispiel finden Sie in den Kommentaren im Code in ISForm und Foxisapi.cpp.
Das "Form Load"-Ereignis
Wenn ISForm erzeugt wird, generiert der Code im Load-Ereignis zwei globale Variablen, gpInstance und gpDisp. Wenn der ISForm-Server zum ersten Mal geladen wird, wird die Variable gpInstance auf 1 festgelegt. Nachfolgende Instanzen erhöhen diese Variable. Wenn eine Instanz gelöscht wird, wird gpInstance verringert.
Die Einsprungpunkt-Methoden
Wenn eine Methode (Cmd, DoSave, Skipit oder Startup) von ISForm durch Foxisapi.dll aufgerufen wird, übergibt die DLL einen Dispatchzeiger als Parameter an die Methode.
Wenn der Server zum ersten Mal geladen wird, wird der Instanzenzähler auf 1 festgelegt und der Dispatchzeiger in der globalen Variable gespeichert. Anschließend wird der Wert 0 im Dispatchzeiger gespeichert.
IF m.gnInstance = 1
IF TYPE('pDisp') $ 'NI'
gpDisp = m.pDisp
pDisp = 0
ENDIF
ENDIF
An diesem Punkt zeigen zwei Variablen auf denselben Wert des Dispatchzeigers: gpDisp im ISForm-Automatisierungsserver und pdispObj in Foxisapi.dll. Der Wert von pdsipDoRelease in der DLL ist 0, wie im ISForm-Automatisierungsserver geändert.
Wenn der Server zu späteren Zeitpunkten aufgerufen wird, wird der Instanzenzähler erhöht, ein neues pdsipObj in der DLL generiert, in pdispDoRelease gespeichert und als Verweis an die angeforderte Methode übergeben. Da der Wert von gnInstance nicht 1 ist, wird die Variable gpDisp nicht geändert. Ab diesem Punkt enthält gpDisp im Automatisierungsserver einen anderen Wert als pdispObj und pdispDoRelase in der DLL.
Code in der DLL
Der folgende C++-Code in Foxisapi.cpp verwaltet das Freigeben des Servers. Nachdem die erste Instanz erzeugt wurde, werden nachfolgende Instanzen normalerweise mit dem Release( )-Aufruf in CallObject( ) in Foxisapi.cpp freigegeben, da pdispObj und pdispDoRelease auf denselben Wert ungleich 0 festgelegt sind.
if (pdispDoRelease != 0) {
pdispObj->Release(); //nonzero, so release the current object
if (pdispObj != pdispDoRelease) {
__try {
(pdispDoRelease)->Release();
} __except (EXCEPTION_EXECUTE_HANDLER) {
}
}
}
Das Destroy-Ereignis von ISForm verringert den Instanzenzähler. Ist nur eine Instanz vorhanden, wurde pdispDoRelease auf 0 festgelegt und wird der Freigabecode nicht aufgerufen. Wenn pdispObject und pdispDoRelease gleich sind, werden nachfolgende Instanzen freigegeben, die originale Instanz wird jedoch nicht freigegeben.
Freigeben des Servers
Um eine Freigabe zu erzwingen, darf pdispDoRelease nicht gleich 0 sein und muss einen anderen Wert als pdispObject haben. Der folgende HTML-Text sendet einen Wert an den Server, der ein Freigeben bewirkt.
<FORM ACTION = "/scripts/foxisapi.dll/foxis.employee.cmd">
<INPUT NAME="Cmd" VALUE = "Reset">
<INPUT TYPE="submit" VALUE="Dos Command">
</FORM>
Der folgende Code in der cmd-Methode legt den Wert von pdispDoRelease auf den Dispatchwert der ersten Instanz fest.
CASE 'RESET'$upper(m.p1)
m.pDisp= m.gpDisp
Code in der DLL gibt jetzt die jeweils aktuelle und die ursprüngliche Instanz frei, die beibehalten wurde, damit die Visual FoxPro-Laufzeitumgebung nicht jedes Mal geladen werden musste, wenn der Server aufgerufen wurde.
Zurücksenden von HTML an den Client
Die GenHTML-Methode der ISForm-Klasse wird von jeder der Einsprungpunkt-Methoden aufgerufen. Der HTML-Code, der von der GenHTML-Methode zurückgegeben wird, wird durch Internet Information Server an den Webbrowser zurückgegeben.
Wenn der mode-Parameter, der an GenHTML übergeben wird, nicht "FORM" lautet, sucht die GenHTML-Methode einfach nach dem Wert in einer Tabelle und sendet vorformatierten HTML-Code zurück.
IF m.mode != 'FORM'
=SEEK(m.mode,'html')
rv = html.html
RETURN m.rv
ENDIF
Wenn der mode-Parameter "FORM" lautet, identifiziert Code in GenHTML jede Bezeichnung und jedes Textfeld im Formular, sortiert sie in absteigender Reihenfolge und von links nach rechts, wertet die Eigenschaften Caption und ControlSource der Steuerelemente aus und verwendet die Visual FoxPro-Funktionalität zum Zusammenführen von Text, um den entsprechenden HTML-Text zu konstruieren, der das Formular annäherungsweise darstellt.
Wenn Sie zu dem Formular zusätzliche Bezeichner und Textfelder hinzufügen, werden diese automatisch im generierten HTML-Code angezeigt.
Erstellen und Verwenden von Cookies
Als Webserver kann diese Anwendung dutzende Male von verschiedenen Clients aufgerufen werden, während wir den Benutzerstatus mitverfolgen müssen. In diesem Fall verfolgen wir nur die aktuelle Datensatznummer für diesen Benutzer. Wir könnten dem Benutzer einen Anmeldebildschirm präsentieren und seinen Benutzernamen als Schlüssel für das Cookie verwenden. Stattdessen generieren wir einen Cookiewert mit Hilfe der MakeCookie-Methode und übergeben ihn als ausgeblendeten Wert in HTML zurück an den Benutzer. Jedes Mal, wenn der Benutzer einen anderen Datensatz auswählt, können wir den Cookiewert von der HTTP-Zeichenfolge lesen, die an die DLL gesendet wird, das Cookie in der Cookies-Tabelle suchen, die aktuelle Datensatznummer finden und die Datensatznummer relativ zu dieser Nummer verschieben.
Die folgenden Eigenschaften und Methoden werden im Cookieveränderungsprozess verwendet:
- Cookie-Eigenschaft
- GetCookie-Methode
- MakeCookie-Methode
- WriteCookieInfo-Methode
Fehlerbehandlung
Wenn ein Fehler auftritt, ruft Code im Error-Ereignis der ISForm-Klasse die GenHTML-Methode mit dem Parameterwert "ERROR" auf. GenHTML liest den vorformatierten HTML-Text für Fehler und gibt ihn an den Error-Ereigniscode zurück. Der Error-Ereigniscode ersetzt Fehlerinformationen für Platzhalter im HTML-Code.
LOCAL rv
rv = THIS.GenHTML('ERROR')
rv = strtran(m.rv,'%METHOD%',m.cMethod)
rv = strtran(m.rv,'%ERRORNO%',STR(m.nError,4))
rv = strtran(m.rv,'%ERRORMSG%',Message(1))
rv = strtran(m.rv,'%LINENO%',STR(m.nLine,4))
THIS.ErrorHTML = m.rv
Wenn die ErrorHTML-Eigenschaft nicht leer ist, sendet GenHTML den Wert von ErrorHTML zurück an den Client.
Tabellen, die im FoxIs-Beispiel verwendet werden
Zusätzlich zu der Mitarbeitertabelle (Employee), die für Dateneingabe und -anzeige verwendet wird, verwendet das FoxIs-Beispiel die folgende Tabellen.
Tabelle | Beschreibung |
---|---|
HTML | Enthält HTML-Text, der an den Webbrowser als Vorspann für FoxCMD- und DosCMD-Auswertungen oder bei Auftreten eines Fehlers zurückgesendet wird. |
Cookies | Verfolgt die Datensatznummern für verschiedene Webbrowser. Der eindeutige Wert des Cookie-Feldes wird als ausgeblendeter Wert im HTML-Text an einen bestimmten Benutzer gesendet. |
Siehe auch
Lösungsbeispiele | Beispiele für FoxISAPI-Automatisierungsserver | FoxWeb, ein vereinfachter Visual FoxPro-Internetautomatisierungsserver