Marc-Hendrik Bremer: Verschiedene Drucker ansprechen

Hallo,

ich bin dabei ein Eintrittskarten-System für unser kleines Kino hier in Dänemark zu entwickeln. Ich benutze php/javascript/mysql und das System läuft im Browser. Soweit alles super.

Wir brauchen aber zwei verschiedene Drucker: Einen für die Eintrittskarten (vorgedruckt auf Rolle) und einen für die Kassenberichte am Tagesende etc. (normaler DinA4-Drucker).
Ich würde nun gerne automatisch den einen oder anderen Drucker ansprechen, je nachdem, welche Aufgabe gerade anliegt (Eintrittskarte drucken oder etwas anderes). Ich habe trotz intensiver Suche keine Möglichkeit gefunden, hoffe aber, daß es eine Möglichkeit gibt (ein Shellscript vielleicht?).

Hat jemand eine Idee?

Vielen Dank,
Marc-Hendrik

  1. Hi,

    Ich benutze php/javascript/mysql und das System läuft im Browser.

    Du läßt PHP im Browser laufen? Sehr ungewöhnlich.

    Wir brauchen aber zwei verschiedene Drucker: Einen für die Eintrittskarten (vorgedruckt auf Rolle) und einen für die Kassenberichte am Tagesende etc. (normaler DinA4-Drucker).
    Ich würde nun gerne automatisch den einen oder anderen Drucker ansprechen, je nachdem, welche Aufgabe gerade anliegt (Eintrittskarte drucken oder etwas anderes). Ich habe trotz intensiver Suche keine Möglichkeit gefunden, hoffe aber, daß es eine Möglichkeit gibt (ein Shellscript vielleicht?).

    Von wo aus soll gedruckt werden?
    Vom Browser aus? Dann: keine Chance, das höchste, was Du per Webseite erreichen kannst, ist, den Print-Dialog per Javascript zu öffnen.

    Vom Server (PHP-Script) aus?
    Dann dürfte es vom Betriebssystem abhängen.

    cu,
    Andreas

    --
    Warum nennt sich Andreas hier MudGuard?
    O o ostern ...
    Fachfragen per Mail sind frech, werden ignoriert. Das Forum existiert.
    1. Hallo,

      Du läßt PHP im Browser laufen? Sehr ungewöhnlich.

      Nein, PHP läuft natürlich - wie auch mySQL - auf einem Webserver (Apache, Xampp) allerdings auf dem lokalen Rechner.

      Von wo aus soll gedruckt werden?
      Vom Browser aus? Dann: keine Chance, das höchste, was Du per Webseite erreichen kannst, ist, den Print-Dialog per Javascript zu öffnen.

      Vom Server (PHP-Script) aus?
      Dann dürfte es vom Betriebssystem abhängen.

      Der Browser soll das Drucken anstoßen, ja. Im Moment mache ich genau das: per Javascript den Printdialog anstoßen. Blöd nur, daß ich weder die Einstellungen ändern kann, noch den Drucker auswählen. Und da wir ca. 75 (ehrenamtliche) Mitarbeiter haben, die das bedienen müssen, ist alles, was automatisch geht ein Gewinn.

      Meine (vielleicht naive) Vorstellung: Ein kleines Script auf dem Server, daß die Daten an den richtigen Drucker weiterreicht. Nur, wie stoße ich es an und wie müsste es (ungefähr) aussehen?
      Betriebssystem ist Windows Vista.

      Viele Grüße,
      Marc-Hendrik

      1. Hallo,

        Wie MudGuard schon schreibt, hast Du wohl keine Chance, mit dem, was der Server an den Browser, d.h. den Client schickt (also HTML/CSS/JavaScript oder ein PDF), zu bestimmen, auf welchem Drucker der Client die Sachen ausdruckt.

        Du könntest aber, wie er auch schon anregt, direkt vom Server aus drucken.
        D.h. wenn Du per Browser ein PHP-Skript aufrufst, sorgt dieses dafür, dass auf dem Server z.B. ein PDF-Dokument generiert wird und anschliessend auf dem Server gedruckt wird.
        Damit wir Dir da weiterzuhelfen können, müsstest Du aber schon genauer spezifizieren, wie der Server aussieht (insbesondere Betriebssystem, Details zur PHP-Installation u.s.w.)

        Was mir aber auch noch in den Sinn kommt:
        Normalerweise merkt sich ja jedes Programm, auf welchem Drucker es zuletzt gedruckt hat, mit welchem Papierformat u.s.w.

        Du könntest also eventuell zwei verschiedene Browser verwenden, einen für die Tickets und einen für den Bericht am Tagesende. Z.B. Firefox für die Tickets (druckt immer auf dem Streifendrucker) und MS IE für den Bericht, sowie für weitere Dinge (druckt immer auf dem DIN-A4-Drucker).

        Auch der Adobe Reader (auch als Plugin) merkt sich einen eigenen Drucker. Du könntest also z.B. die Tickets als HTML und den Bericht als PDF ausliefern. Der Browser selbst druckt dann auf den Streifendrucker, Adobe Reader auf den DIN-A4-Drucker. Das müsstest Du halt ausprobieren. Mit Firefox 3.6 und Adobe Reader 9 scheint es - auch unter Windows Vista - jedenfalls zu funktionieren.

        HTH, mfg
        Thomas

        1. Hallo zusammen,

          danke erst mal für die Anregungen!

          Wir haben einen Rechner im Kino, auf dem läuft Windows Vista und ich habe einen lokalen Webserver (Apache), samt MySQL darauf installiert (XAMPP-Paket). PHP-Version ist 5.3.1.

          Die Idee mit dem Drucken der Eintrittskarten über den Browser und der Berichte über den Akrobat Reader finde ich schon sehr spannend. Ich habe zwar noch keine PDFs mit PHP generiert, aber es geht ja und sieht auch nicht so unglaublich kompliziert aus.

          Ich habe auch schon gedacht, daß es ja reicht, jeweils den Standarddrucker vorher neu zu bestimmen. Also über ein shell_exec, exec() oder system()-Aufruf ein kleines Skript anzustoßen, daß den Standarddrucker ändert und dann erst den Browser zum Drucken auffordern. Ich habe auch schon gefunden, daß das über Windows Scripting funktioniert:

          Set WshNetwork = CreateObject("WScript.Network")
          WshNetwork.SetDefaultPrinter(strPrinter)

          Und unter http://www.aspfree.com/c/a/Windows-Scripting/Printing-Documents-in-WSH/5/ scheint auch noch ein Weg aufgezeigt, der mir den lästigen Druckerauswahl-Dialog erspart.

          Aber da verlasse ich den Bereich der mir bekannten Programmierumgebungen, daher bräuchte ich zumindest noch ein aufmunterndes Schulterklopfen und einen kleinen Fingerzeig wie das ganz praktisch umzusetzen ist, bevor ich mich da rantraue. Sieht ja simpel genug aus ...
          Wenn also jemand Erfahrung mit Windows Scipting hat, und mich auf die richtige Fährte (gutes Einsteiger-Tutorial?) setzen kann und ihr mir dann noch sagt, ob das mit shell_exec() u.ä. dann auch funktionieren kann, dann wäre mir viel weiter geholfen.

          Vielen Dank,
          Marc-Hendrik

          1. Moin Moin!

            Ich schmeiß nochmal CUPS in die Runde, oder genauer das Internet Printing Protocol. Etwas vereinfacht machst Du einen TCP-Socket auf, sprichst HTTP mit dem Printserver, und übergibst einen Druckjob. Das Rastern kann der IPP-Server übernehmen, oder der Drucker selbst. Der Druckjob kann also Postscript, PCL oder ähliches, aber auch schon fertig "vorverdaut" für den Drucker sein.

            Der Trick ist, dass der Client hier durchaus ein PHP-Script auf dem Webserver sein kann.

            Windows ab 2000 kann auf jeden Fall als Client einen IPP-Server benutzen, es müßte aber auch einen IPP-Server für Windows geben. Letzteren bräuchtest Du. CUPS läuft leider nicht auf Windows, soweit ich weiß.

            Wenn Du Deine Anwendung auf Linux oder *BSD aufsetzen würdest, wäre das etwas einfacher, denn da ist CUPS in aller Regel gleich mit dabei (Apache, MySQL und PHP sowieso). Und wenn Du den Rechner wirklich nur als Kasse mit dem Webbrowser als Frontend benutzt, sehe ich nicht, was dagegen spricht. Ob ein Browser nun auf Windoof oder einem Unix fullscreen läuft, merkt der Benutzer gar nicht. Autostart und Auto-Login lassen sich bei Bedarf auch in Umgebungen wie Gnome, KDE und XFCE (sehr empfehlenswert, schlanker als die beiden anderen) einrichten.

            Zweiter Ansatz, etwas pragmatischer:

            Beide Drucker bekommen einen Printserver, entweder je einen eigenen (wenn nicht ohnehin schon eingebaut) oder einen mit zwei bis drei Druckeranschlüssen. Die werden typischerweise über TCP Port 9100 mit Druckerdaten gefüttert, so wie sie am Drucker ankommen müssen (sprich: Socket auf, Daten rein, Socket zu), bei Multiport-Printservern liegt der erste Port auf TCP Port 9100, der zweite auf 9101, der dritte auf 9102 usw. Manche Printserver können noch viel mehr (LPT, IPP -- siehe oben, Novell, Windows, Apple), aber das primitive Port9100-Protokoll (oft "JetDirect" genannt) aus Zeiten schwacher Hardware beherrschen sie eigentlich alle.

            Als Seitendrucker für die Berichte nimmst Du einen monochromen Laserdrucker mit Postscript, dem drückst Du direkt aus PHP heraus Postscript rein. Den den Kartendrucker wirst Du vermutlich ohnehin mit seinen eigenen, sehr speziellen Steuersequenzen bedienen müssen, über die Du außerhalb des Browsers wesentlich mehr Kontrolle hast.

            Beide Ansätze lassen sich kombinieren, insbesondere wenn der Server ein Unix-Derivat ist, denn natürlich beherrscht auch CUPS das Port9100-Protokoll.

            Mit einem Unix-Derivat auf einem dedizierten Server läßt sich dann auch gleich der nächste Schritt realisieren: Mehrere Kassen als Thin Clients laden ihr Betriebssystem mitsamt lokalen Webbrowser und einem lokalen Port9100-Server vom Server, z.B. mit Etherboot als Bootloader und Thinstation, dem firefox- und dem lp_server-Paket als Betriebssystem. Dann kann der Drucker an der Kassenstation hängen, aber gedruckt wird vom Server via Port9100 oder, etwas komfortabler über CUPS auf dem Server. Die Entscheidung, auf welchen Drucker eine Eintrittskarte gedruckt werden soll, ist dann ganz einfach: Immer auf den, zu dem die REMOTE_ADDR gehört, die der Webserver an PHP weiterreicht.

            Thin Clients mußt Du übrigens nicht neu kaufen, dafür eignet sich fast jeder alte PC, dem Du eine Netzwerkkarte mit Boot-PROM oder eine Boot-Diskette (auch mit Etherboot) verpaßt, wahlweise kannst Du auch Thinstation von CD starten, dann muß aber in jeder Kasse ein CD-Laufwerk stecken. Mit dem Boot-Prom kann der Kassenrechner komplett ohne Massenspeicher laufen, keine Floppy, keine Festplatte, kein CD-Laufwerk. Das spart jede Menge Platz, Strom und letztlich auch Abwärme, wodurch oft auch der letzte Lüfter entfallen oder stark heruntergeregelt werden kann.

            Alexander

            --
            Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
            1. Moin Alexander,

              das hört sich sehr professionel an - wäre in diesem Falle aber, glaube ich, overkill.
              Es ist wirklich nur ein kleines Kino - und das bleibt es auch ;-) Eine Kasse, dann später noch eine Website für Online-Reservierung.

              Der Kartendrucker ist zum Glück über einen Treiber als normaler Drucker anzusprechen und ich muß mich nicht groß mit Steuersequenzen herumschlagen.
              Je einfacher, desto besser - nicht nur, weil ich eher Quereinsteiger bin, sondern auch, weil ich möglicherweise irgendwann nicht mehr da bin und die Anzahl der Computerversteher hier auf dem Dorfe doch ziemlich gering - zumindest im Verein, der das Kino betreibt.

              Trotzdem vielen Dank, das war für mich durchaus sehr erhellend!

              Grüße aus Nordjydland,
              Marc-Hendrik

              1. Moin Moin!

                das hört sich sehr professionel an

                Bringt der Beruf so mit sich ... ;-)

                wäre in diesem Falle aber, glaube ich, overkill.
                Es ist wirklich nur ein kleines Kino - und das bleibt es auch ;-) Eine Kasse, dann später noch eine Website für Online-Reservierung.

                Naja, dann brauchst Du die Extra-Spielereien für mehrere Kassen ja nicht umzusetzen, und alles kann auf einer Maschine bleiben.

                Der Kartendrucker ist zum Glück über einen Treiber als normaler Drucker anzusprechen und ich muß mich nicht groß mit Steuersequenzen herumschlagen.

                Sehr schön.

                Je einfacher, desto besser - nicht nur, weil ich eher Quereinsteiger bin, sondern auch, weil ich möglicherweise irgendwann nicht mehr da bin und die Anzahl der Computerversteher hier auf dem Dorfe doch ziemlich gering - zumindest im Verein, der das Kino betreibt.

                Und dann Windows mit einem Apache-PHP-MySQL-Stack, der sich irgendwo in den Services versteckt? Ich weiß nicht, ich weiß nicht. Denk mal über Linux oder *BSD nach, schon allein, weil CUPS dir die Arbeit mit den Druckern recht leicht machen müßte. Wenn Du keine Library für IPP in PHP findest, kannst Du auch stumpf über den Kompatibilitätslayer für das alte LPR-System arbeiten, sprich: Du startest /usr/bin/lpr so, dass PHP den Druckjob in STDIN von lpr schreibt.

                In Perl sähe dass sinngemäß so aus:

                  
                open my $lpr,'| /usr/bin/lpr -PKartendrucker' or die "lpr open fehlgeschlagen: $!";  
                print $lpr "KINO Wasauchimmer\nFreier Eintritt auf Lebenszeit\nKaufpreis: 123456.78 EUR\n" or die "lpr print fehlgeschlagen: $!";  
                #           ^-- typischerweise Postscript, möglich: alles was CUPS filtern kann  
                close $lpr or die "lpr close fehlgeschlagen: $!";  
                
                

                PHP-Code dürfte fast genauso aussehen. Noch viel einfacher kann man nicht drucken. Die Kunst ist in dem Fall eher, ein Template auszufüllen und in verdaubarer Form an CUPS zu übergeben. Was CUPS verdauen kann, legen Filter fest, das können wiederum beliebige Scripte sein.

                Irgendwo in meinem Hinterkopf spukt auch noch rum, dass es Windows Services for UNIX und ähnliches gibt, vielleicht bekommt man die Kombination aus lpr und dem entsprechenden Druckserver (lpd) auch auf Windows hin, dann würde das so auch unter Windows funktionieren, nur eben ohne die nette Filterautomatik von CUPS. Einen LPD gibt es jedenfalls für Windows.

                Alexander

                --
                Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
                1. And the answer is ...

                  Hallo zusammen,

                  ich habe eine einfache Lösung gefunden - sicher nicht die Beste aber in meinem Fall ausreichend.

                  Der Standardprinter wird gesetzt durch:

                  shell_exec('rundll32 printui.dll,PrintUIEntry /y /n "Printername"');

                  Und eine Konfiguration, die man vorher mit /Ss abgespeichert hat, kann man mit
                  shell_exec('rundll32 printui.dll,PrintUIEntry /Sr /n "Printername" /a "filename.dat" u');
                  wieder laden, was z.B. das Umschalten zwischen Papiergrößen ermöglicht.

                  Danke für eure Unterstützung und die Ideen!

                  Viele Grüße aus dem (verregneten) Norden,
                  Marc-Hendrik

                  1. Moin Moin!

                    Der Standardprinter wird gesetzt durch:

                    shell_exec('rundll32 printui.dll,PrintUIEntry /y /n "Printername"');

                    Und eine Konfiguration, die man vorher mit /Ss abgespeichert hat, kann man mit
                    shell_exec('rundll32 printui.dll,PrintUIEntry /Sr /n "Printername" /a "filename.dat" u');
                    wieder laden, was z.B. das Umschalten zwischen Papiergrößen ermöglicht.

                    Cleverer Ansatz -- das funktioniert natürlich nur, so lange Browser und PHP auf der selben Maschine laufen.

                    Solltest Du doch irgendwann mal auf mehrere Maschinen umsteigen, könntest Du den RunDLL-Aufruf bzw. das Aufrufen der entsprechenden DLL-Funktion auch aus dem Browser heraus machen. Dafür muß aber zwingend im Browser priviligierter Code laufen, sei es browserübergreifend ein signiertes Java-Applet, ein (selbstgestricktes) ActiveX-Control für den IE oder Plugin für den Firefox, oder auf sonst irgendeine Art.

                    Alexander

                    --
                    Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
                    1. Hej igen!

                      Cleverer Ansatz -- das funktioniert natürlich nur, so lange Browser und PHP auf der selben Maschine laufen.

                      Ja, tatsächlich gibt es schon Probleme, wenn Browser und Server nicht unter dem gleichen Benutzer laufen. Dann ändert der Aufruf den Standarddrucker des Server-Benutzers, der Browser druckt aber natürlich vom Browser-Benutzer aus.
                      Auch da würde dein Ansatz mit einem Applet/ActiveX/Plugin helfen. Ich werde das im Hinterkopf behalten, für uns hier konnte ich das Problem lösen indem Server und Browser nun unter dem gleich Nutzer laufen.

                      Schön, daß es auf dieser Welt so viel zu lernen gibt - und noch besser, daß es Menschen gibt, die bereit sind einem dabei zu helfen. :-)

                      Viele Grüße,
                      Marc-Hendrik