Willkommen
Willkommen
\\
Diese recht überschaubare HTML-Datei stellt drei Schaltflächen mit der Beschriftung **Versand**, **Lager** und **Büro** zur Verfügung, die auf die Statusanzeige für die jeweilige Abteilung verweisen. Damit die Statusanzeige weiss, welche Drucker zu welcher Abteilung gehören, wird die Liste der Drucker als Textdatei übergeben. In einer solchen Datei stehen einfach die Namen der zu überwachenden Drucker oder Gateways. Jeweils ein Name je Zeile.
Die zweite HTML-Seite, die benötigt wird, ist die, die zur Statusanzeige verwendet werden soll. Der erste Teil der Datei (CSS) ist identisch mit der der Startseite, um ein einheitliches Bild zu gewährleisten. Diese Seite wird unter dem Namen **Template.html** abgelegt, weil sie nicht direkt angezeigt werden kann, sondern erst noch durch ein Skript bearbeitet wird. Der HTML-Code ist nachfolgend abgebildet.
\\
Druckerstatus
Druckerstatus
Zuletzt aktualisiert:
\\
Das einzig Besondere an diesem HTML-Code sind die drei als Kommentare eingefügten Platzhalter, die bei der Bearbeitung durch ein Perl-Skript durch weiteren HTML-Code ersetzt werden. Soweit der HTML-Code.
\\
Ein weiterer wichtiger Bestandteil der Lösung sind zwei kleine Perl-Skripte. Das erste Skript hat den Namen **remote.pl** und wird von der Startseite aus aufgerufen. Beim Aufruf wird der Name der Textdatei mit den Drucker- und Gateway-Namen als Parameter **Drucker** übergeben.
Am Anfang des Skriptes werden zwei Umsetzungstabellen (Hashes **%Flaggen** und **%Druckerstatus**) definiert. Diese dienen zum einen zur Auswahl einer den Status des Druckers anzeigenden farbigen Flagge und zum anderen zur Anzeige des Druckerstatus im Klartext.
\\
#!"C:\perl\bin\perl.exe"
my %Flaggen = (
100 => "Grey.gif",
101 => "Yellow.gif",
102 => "Green.gif",
103 => "Cyan.gif",
104 => "Magenta.gif",
105 => "White.gif",
106 => "Red.gif",
110 => "Blue.gif",
111 => "Blue.gif",
112 => "Blue.gif",
113 => "Blue.gif",
114 => "Blue.gif",
115 => "Blue.gif",
116 => "Blue.gif",
117 => "Blue.gif"
);
my %Druckerstatus = (
100 => "Angehalten",
101 => "Bereit",
102 => "Druckt",
103 => "Lizenzanfrage",
104 => "Druckeranfrage",
105 => "",
106 => "Fehler",
110 => "Eingriff erforderlich",
111 => "Papierstau",
112 => "Papierende",
113 => "Wenig Toner",
114 => "Abdeckung offen",
115 => "Offline",
116 => "Netzwerkverbindung verloren",
117 => "Ausgabefach voll"
);
\\
Der erste Teil des Skripts dient der Aufbereitung der durch den HTTP-Server übergebenen Formularparameter. Die Komplexität dieser Anweisungen ist der aufwändigen Umkodierung von Steuerzeichen und in HTML selbst benutzten Zeichen innerhalb der Formularparameter geschuldet. Die Formularparameter werden als Paare aus Namen und Werten abwechselnd im Feld **$Parameter** untergebracht.
Anschliessend liest das Skript die HTML-Datei **Template.html** und sucht über einen regulären Ausdruck nach den Kommentarzeilen. Enthält der Kommentar den Text **Datum**, wird das aktuelle Datum und Uhrzeit ermittelt und statt des Kommentars in die Ausgabe eingesetzt. Enthält der Kommentar den Text **Liste**, wird ein Formularparameter statt des Kommentars erzeugt, der einfach den Namen der Textdatei weitergibt.
Das Entscheidende passiert, wenn der Kommentar den Text **Drucker** enthält. In diesem Fall wird die als Parameter übergebene Textdatei geöffnet, die Druckernamen werden gelesen und an eine Prozedur mit dem Namen **DruckerStatus** übergeben. Diese Prozedur ermittelt für jeden Drucker dessen aktuellen Status.
Wichtigster Bestandteil dieser Prozedur ist der Aufruf des mit der Installation von (c4p) mitgelieferten Hilfsprogramms **c4pRemote**, Dieses Hilfsprogramm gestattet eine gegenüber dem Kontrollfeld etwas eingeschränkte Steuerung des Konverter/Gateway-Servers via Kommandozeile - eine Beschreibung dieses Programms findet sich übrigens im vorangegangenen Kapitel.
Das Programm **c4pRemote** wird mit dem Parameter '-q' für eine Statusanfrage und dem als Prozedurparameter übergebenen Druckernamen aus der Textdatei aufgerufen. Aus dem Rückgabewert des Programms wird dann der HTML-Code für die Statusanzeige erzeugt.
\\
#------------------------------------------------------------------------------#
if ($ENV{'REQUEST_METHOD'} eq 'GET')
{
my @ParameterListe = split(/&/, $ENV{'QUERY_STRING'});
my $i = 0;
foreach $Param (@ParameterListe)
{
($Parameter [$i], $Parameter [$i + 1]) = split(/=/, $Param);
$i++;
$Parameter [$i] =~ tr/+/ /;
$Parameter [$i] =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$Parameter [$i] =~ s///g;
$i++;
}
open (TMPL, ")
{
if (/^.*/)
{
if ($1 eq "Datum")
{
($sec, $min, $hour, $mday, $mon, $year, $wday, $yday)
= localtime (time);
$year += 1900;
$mon +=printf "%02d.%02d.%04d %02d:%02d:%02d\n",
$mday, $mon, $year, $hour, $min, $sec;
}
elsif ($1 eq "Drucker")
{
open (PRT, "<$Parameter[1]");
while ()
{
chomp ($_);
DruckerStatus ($_);
}
close (PRT);
}
elsif ($1 eq "Liste")
{
print "\n";
}
}
else { print $_; }
}
close (TMPL);
}
#------------------------------------------------------------------------------#
sub DruckerStatus
{
$Status = system ("C:\\Programme\\convert4print\\c4pRemote",
"-q",
"-n\"$_[0]\"") / 256;
print "\n";
print " \n";
print " \n";
print " \n";
print " \n";
print " $_[0] \n";
print " $Druckerstatus{$Status} \n";
print " \n";
}
#------------------------------------------------------------------------------#
\\
Der bereits letzte Bestandteil der Lösung ist ein weiteres Skript **update.pl**, welches aufgerufen wird, wenn eine der vier Schaltflächen unterhalb der Tabelle angeklickt wird. Welche der Schaltflächen angeklickt wurde, entnimmt das Skript dem verdeckt übermittelten Formularparameter **Aktion**, der von jeder Schaltfläche via JavaScript entsprechend gesetzt wird.
Die erste Hälfte des Skripts dient wieder der Aufbereitung der durch den HTTP-Server übergebenen Formularparameter und ist ähnlich mit den Anweisungen aus dem ersten Skript. Allerdings bezieht sich hier die Aufbereitung auf die als Parametername übermittelten Druckernamen.
Der einfachste Fall für das Skript ist die Aktualisierung der Anzeige, weil dies lediglich den erneuten Aufruf des Skriptes **remote.pl** bedeutet. Dabei muss der als zweiter Parameter an das Skript übergebene Name der Textdatei erneut übergeben werden.
In allen anderen Fällen (Starten, Anhalten, Abbrechen) wird wieder das Programm **c4pRemote** aufgerufen, diesmal allerdings zusätzlich parametrisiert mit der durch die Schaltfläche vorgegebenen Aktion, also '-s' für **Starten**, '-t' für **Anhalten** und '-a' für **Abbrechen**. Der zweite Parameter ist wieder der Druckername.
\\
#!"C:\perl\bin\perl.exe"
if($ENV{'REQUEST_METHOD'} eq 'GET')
{
my @ParameterListe = split(/&/, $ENV{'QUERY_STRING'});
my $i = 0;
foreach $Param (@ParameterListe)
{
($Parameter [$i], $Parameter [$i + 1]) = split(/=/, $Param);
$Parameter [$i] =~ tr/+/ /;
$Parameter [$i] =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$Parameter [$i] =~ s///g;
$i++; $i++;
}
if ($Parameter [1] ne 'u')
{
while ($i > 2)
{
$i--; $i--;
system ("C:\\Programme\\convert4print\\c4pRemote",
"-$Parameter[1]",
"-n\"$Parameter[$i]\"");
}
}
print "Location: http://$ENV{'HTTP_HOST'}/cgi-bin/remote.pl?"
. "$Parameter[2]=$Parameter[3]\n\n";
}
exit 0;
\\
Die Liste der ausgewählten Drucker (oder Gateways) wird über eine Schleife beginnend mit dem als letzten ausgewählten Drucker abgearbeitet. Sollte übrigens das Installationsverzeichnis von (c4p) nicht **C:\Programme\convert4print** sein, ist der Programmaufruf in beiden Skripten entsprechend abzuändern.
\\
Bisher nicht weiter erwähnt wurde, daß die Lösung noch eine Reihe von Graphikdateien benötigt. Zum einen die acht möglichen Flaggen zur Statusanzeige und natürlich das (c4p)-Logo. Alle diese Dateien befinden sich in einem Ordner mit dem Namen **imgs**.
Die beiden Skripte **remote.pl** und **update.pl** gehören ins CGI-Verzeichnis des HTTP-Servers, genauso wie die Datei **Template.html** und alle Textdateien mit den Druckernamen - im Falle von Apache also nach **C:\xxamp\cgi-bin**. Die Seite **convert4print.html** wurde im Beispiel auf die Hauptebene des Servers kopiert, kann aber natürlich abhängig von den lokalen Gegebenheiten auch in jedem Unterverzeichnis liegen. Im Falle von Apache wird die Datei **convert4print.html** ins Verzeichnis **C:\xxamp\htdocs** kopiert. Dorthin wird auch der Ordner **imgs** mit den Bildern kopiert.
Wenn die Datei **convert4print.html** für den HTTP-Server nicht prinzipiell als Startseite angegeben wird, erfolgt der Aufruf im Browser mit **http://c4p.spe-systemhaus.de/convert4print.html**, wobei der Servername natürlich an die lokalen Gegebenheiten angepasst werden muss.
\\
Bereits mit so überschaubarem Aufwand ist also eine Lösung für die Druckerüberwachung und Steuerung im Intranet zu realisieren. Dadurch, dass nur der HTTP-Server Zugriff auf die Rechner mit der (c4p)-Installation hat, ist keine aufwändige Konfiguration von Zugriffsrechten erforderlich. Für die HTTP-Zugriffe kann auf das zumeist bereits im Intranet vorhandene Zugriffskontrollsystem zurückgegriffen werden, und auf dem Rechner des jeweiligen Mitarbeiters ist nur ein Internet-Browser notwendig.
\\
Zum Abschluß sei noch kurz erwähnt, was zu ändern ist, wenn (c4p) nicht auf dem gleichen Rechner installiert ist, wie der Web-Server. In diesem Fall muß der Web-Server die Ausführung des Programms **c4pRemote** auf dem Rechner mit der (c4p)-Installation veranlassen. Dazu kann von **www.sysinternals.com** das Paket **PsTools** geladen werden, das ein Programm mit dem Namen **PsExec.exe** enthält.
**PsExec.exe** führt ein als Parameter übergebenes Kommando auf einem anderen Rechner aus. Eine Beschreibung des Programms findet sich in der der Tool-Sammlung beiliegenden Dokumentation. Im Skript **remote.pl** muß demnach der Programmaufruf wie folgt geändert werden:
\\
$Status = system ("C:\\Programme\\Sysinternals\\psexec",
"\\\\10.1.17.7",
"-u",
"Benutzer",
"-p",
"Passwort",
"D:\\Programme\\convert4print\\c4pRemote.exe",
"-q",
"-n\"$_[0]\"") / 256;
\\
Dem entsprechend sieht der Programmaufruf im Skript **update.pl** dann so aus:
\\
system ("C:\\Programme\\Sysinternals\\psexec",
"\\\\10.1.17.7",
"-u",
"Benutzer",
"-p",
"Passwort",
"D:\\Programme\\convert4print\\c4pRemote",
"-$Parameter[1]",
"-n\"$Parameter[$i]\"");
\\
Dabei wird angenommen, daß das Tool **PsExec** im Verzeichnis **C:\Programme\Sysinternals** liegt, daß der andere Rechner die IP-Adresse '10.1.17.7' hat, und daß dort die (c4p)-Installation auf **D:\Programme\convert4print** erfolgte. Ein weiterer wesentlicher Punkt ist, daß auch eventuell die Anmeldung als Benutzer auf dem anderen Rechner notwendig ist.
Zu dieser Lösung ist allerdings zu sagen, daß sie sehr teuer ist, im Sinne von Prozessor- und Netzwerklast (ca. 300 KByte / Zugriff). Auch aus Sicht der Systemsicherheit ist das Erlauben von Remote-Zugriffen durch andere Rechner nicht immer gern gesehen. Dieses Vorgehen sollte daher wirklich nur in Ausnahmefällen zum Einsatz kommen.
\\
=== Hinweise ===
* Das Programm **c4pRemote** arbeitet ohne Wissen eines möglicherweise offenen Kontrollfeldes. Von daher können sich im Kontrollfeld recht ungewöhnliche Statusänderungen zeigen, die durch das im Hintergrund aufgerufene Programm verursacht sind. Insofern sollte man sich als Nutzer des Kontrollfeldes der Fremdsteuerung immer bewußt sein.
* Das Programm **c4pRemote** selbst erkennt zur Zeit keine Mehrfachaufrufe. Sind mehrere Verwaltungs- oder Überwachungssysteme gleichzeitig im Einsatz, kann es zu unerwarteten Reaktionen kommen, da keine zeitliche Synchronisation beim Zugriff auf den Dienst stattfindet. Solche Fälle können allerdings durch geeignete organisatorische Maßnahmen leicht vermieden werden (nicht mehrere Überwacher für einen Drucker).
* Der Aufruf des Programms **c4pRemote** stellt eine gewisse Last für den HTTP-Server dar, weil es ja immer als eigener Prozess neu gestartet wird. Von daher sollte ein automatischer Update der HTTP-Seite zum Beispiel mit Hilfe von JavaScript nur erwogen werden, wenn dies wirklich notwendig ist. Die Zeitintervalle, die dabei gewählt werden sollten, sollten fünf Sekunden sicher nicht unterschreiten. Auch sollten nicht viel mehr als etwa fünf Drucker pro Mitarbeiter so überwacht werden.
* Beim Aufruf des Programms **c4pRemote** aus dem Web-Server heraus muß natürlich sichergestellt sein, daß das Systemkonto, unter dem der Web-Server in der Regel läuft, auch Mitglied in der Gruppe der **c4pUser** oder **c4pAdmins** ist, weil es sonst beim Zugriff auf die Registry des Konverter/Gateway-Services zu einer Rechteverletzung kommt. Beim Zugriff über das Tool **PsExec** ist das nicht notwendig, weil über die Kommandozeile eine richtige Anmeldung auf dem anderen Rechner erfolgen kann.
* Die hier vorgestellte Lösung ist auch genau so auf dem IIS eines Windows-Servers lauffähig. Allerdings muß zur Ausführung der Skripte ein Perl-Paket auf dem Server installiert sein, z.B. ActivePerl 5.10. Bei der Verzeichnissicherheit muß natürlich peinlichst darauf geachtet werden, daß entweder eine Anmeldung am IIS erfolgen muß, und die betreffenden Benutzerkonten Mitglieder der Gruppe **c4pUsers** oder **c4pAdmins** sind, oder daß das Konto, das für den anonymen Zugriff verwendet wird, ebenfalls Mitglied in einer dieser Gruppen ist.