Dienstag, 6. April 2010

Druckerstatus abfragen - Teil 2 / Query printer status - Part 2

Im Dezember hatte ich einen Eintrag verfasst, in dem es darum ging, den Status der vorhandenen Drucker abzufragen. Im folgenden Codebeispiel habe ich diese Funktionalität dahingehend erweitert, dass nun auch der Standarddrucker des aktuellen Benutzers gefunden und gekennzeichnet wird.

Ermöglicht wird dies durch eine Abfrage des Windows-Spoolertreibers (winspool.drv) der sich üblicherweise im Windows System- und/oder System32-Verzeichnis befindet.

Der u.a. Code baut auf den bereits im Dezember Posting gezeigten Funktionen GetPrinterStatus() und GetPrinterStatusAsText() auf. Neu hinzugekommen sind die Funktionen DisplayPrinterInfos() sowie GetDefaultPrinter() welche innerhalb von GetPrinterStatus() direkt aufgerufen wird. Ebenfalls neu ist, dass nun sämtliche Daten in einem Cursor vorgehalten werden.

DisplayPrinterInfos() erweitert die _SCREEN-Ausgabe um Druckerstandort und Kommentar. GetDefaultPrinter() greift auf die API-Funktion 'GetDefaultPrinter' aus winspool.drv zurück. Hierbei habe ich den API-Funktionsnamen mit einem Alias ( -> MyDefaultPrinter) versehen, damit meine identische interne Funktionsbenamung keine Rekursion verursacht.

LOCAL liFlag as Integer

* // installierte Drucker überprüfen und entsprechenden Cursor erzeugen    
=APRINTERS(laPrn,1)

* // Leeren Cursor erzeugen 
CREATE CURSOR crsprinters ( ;
    prn_type        C(  1), ;
    prn_default     C(  1), ;
    prn_printer     C(250), ;
    prn_port        C( 50), ;
    prn_driver      C(100), ;
    prn_comment     C(250), ;
    prn_location    C(250), ;
    prn_status      C( 30) ;
    )

* // Wurden installierte Drucker gefunden, dann wird nun der Inhalt        
* // des Arrays in einer Schleife verarbeitet und an 'crsPrinters'         
* // übergeben. 
IF !EMPTY(laPrn(1,1))
    FOR liFlag = 1 TO ALEN(laPrn,1)
        IF SUBSTR(laPrn(liFlag,1),1,2) = [\\]
            m.prn_type       = [n]
            m.prn_printer    = [ ] + laPrn(liFlag,1)
        ELSE 
            m.prn_type       = [l]
            m.prn_printer    = laPrn(liFlag,1)
        ENDIF
        m.prn_port      = laPrn(liFlag,2)
        m.prn_driver    = laPrn(liFlag,3)
        m.prn_comment   = laPrn(liFlag,4)
        m.prn_location  = laPrn(liFlag,5)
        m.prn_default   = [ ]
        m.prn_status    = [ ]
        INSERT INTO crsPrinters FROM MEMVAR 
    ENDFOR 
    * // Nun die noch fehlenden Statusinformationen im Cursor            
    * // hinterlegen und die Ausgaberoutine aufrufen. 
    GetPrinterStatus()
    DisplayPrinterInfos()
    USE IN SELECT([crsPrinters])
ELSE 
    * // Ab und an soll es tatsächlich vorkommen, dass überhaupt kein    
    * // Drucker im System vorhanden ist. Dies sollten wir dem Anwender    
    * // natürlich nicht vorenthalten.
    LOCAL lcString as String
    TEXT TO lcString NOSHOW ADDITIVE TEXTMERGE PRETEXT 2
        A C H T U N G ! ! !
        Für Ihr Login sind noch keine Drucker installiert!
        Zum Ausdrucken von Daten werden diese jedoch zwingend
        benötigt. Bitte installieren Sie über
        
        [Start] - [Einstellungen] - [Drucker] - [Neuer Drucker]
        
        einen oder mehrere Drucker!
    ENDTEXT 
    MESSAGEBOX(lcString,0+64+0,[Kein Drucker installiert])
    RELEASE lcString
ENDIF 

RELEASE laPrn

* // ----------------------------------------- DisplayDefaultPrinter
FUNCTION GetDefaultPrinter as String

    * // Wichtig bei dieser Funktion ist, dass der als Referenz        
    * // übergebene String mit CHR(0) Zeichen vorbesetzt wird.        
    LOCAL liBuffSize as Integer, lcPrinter as String
    liBufsize = 250
    lcPrinter = REPLICATE( CHR( 0 ), liBufsize )
    
    * // Über winspool.drv können wir den aktuellen Standarddrucker    
    * // abfragen. Das Ergebnis liefern wir als String zurück, um    
    * // in der nachfolgenden Verarbeitung einen direkten Namens-    
    * // vergleich durchführen zu können.
    TRY 
        DECLARE INTEGER GetDefaultPrinter IN winspool.drv AS MyDefaultPrinter ;
                STRING  @ pszBuffer,;
                INTEGER @ pcchBuffer

        * // Da die API-Funktion genauso heisst, wie die VFP-Funktion
        * // war eine Umbenennung der API-Funktion mit Hilfe eines    
        * // ALIAS notwendig. Somit wurde aus GetDefaultPrinter() die 
        * // Funktion MyDefaultPrinter.
        = MyDefaultPrinter( @lcPrinter, @liBufsize )
        lcPrinter = SUBSTR(lcPrinter, 1, AT( CHR( 0 ), lcPrinter ) - 1 )
    CATCH 
        lcPrinter = [ ]
    ENDTRY 
    
    RETURN lcPrinter

ENDFUNC 

* // ------------------------------------------- DisplayPrinterInfos
FUNCTION DisplayPrinterInfos
    
    * // Diese Funktion zeigt den Inhalt des Druckercursors an.        
    * // hierbei erfolgt die Kennzeichnung des Standarddruckers über
    * // ein kleines 'x' vor dem Druckernamen.
    
    LOCAL lcFont as String, lcDisplay as String
    
    * // VFP Screen vorbereiten                                        
    lcFont              = _screen.Fontname
    _screen.FontName    = [Courier New]
    CLEAR 
    
    SELECT crsPrinters
    GO TOP 
    ??[Status                   Drucker (x=Standarddrucker)              Standort                            Kommentar                                                             ]
     ?[---------------------------------------------------------------------------------------------------------------------------------------------------------------------------]
    DO WHILE !EOF()
        TEXT TO lcDisplay TEXTMERGE NOSHOW PRETEXT 1+2+4+8
            <<SUBSTR( crsPrinters.prn_status,1,20 )>>
            <<IIF(EMPTY(crsPrinters.prn_default),[   ],[ x ])>>
            <<SUBSTR( crsPrinters.prn_printer,1,40 )>>
            <<SUBSTR( crsPrinters.prn_location,1,35 )>>
            <<SUBSTR( crsPrinters.prn_comment,1,70 )>>
        ENDTEXT 
        ? lcDisplay
        SKIP IN ([crsPrinters])
    ENDDO 
         
    * // VFP Screen zurücksetzen            
    _screen.FontName = lcFont
    
ENDFUNC 

* // ---------------------------------------------- GetPrinterStatus
FUNCTION GetPrinterStatus as String

    LOCAL lcComputer as String, loWMIService as Object, ;
          loInstalledPrinters as Object, lcStatus as String, ;
          lcFont as String, lcDefPrn as String

    * // Arbeitsvariablen initialisieren    
    lcComputer          = [.]
    loWMIService        = GETOBJECT([winmgmts:] + [{impersonationLevel=impersonate}!\\] + lcComputer + [\root\cimv2])
    loInstalledPrinters = loWMIService.ExecQuery([SELECT * FROM Win32_Printer])
    lcFont              = _screen.FontName 
    lcDefPrn            = GetDefaultPrinter()

    * // Druckerobjekt auslesen                
    FOR EACH loPrinter IN loInstalledPrinters

        lcStatus = GetPrinterStatusAsText(loPrinter)

        SELECT crsPrinters
        GO TOP 
        LOCATE FOR prn_printer = loPrinter.Name
        IF FOUND()
            IF LEN(ALLTRIM(lcStatus)) > 15
                REPLACE prn_status WITH SUBSTR(lcStatus,16)   IN crsPrinters
            ELSE 
                REPLACE prn_status WITH SUBSTR(lcStatus,1,15) IN crsPrinters
            ENDIF 
            * // Standarddrucker im Cursor kennzeichnen.
            IF ALLTRIM(crsPrinters.prn_printer) == lcDefPrn
                REPLACE prn_default WITH [x] IN crsPrinters
            ENDIF 
        ENDIF 
        
    NEXT 
ENDFUNC 

* // ---------------------------------------- GetPrinterStatusAsText
FUNCTION GetPrinterStatusAsText as String
LPARAMETERS oPrinter as Object

    LOCAL lcReturn as String
    lcReturn = []
    
    DO CASE 
    CASE oPrinter.PrinterStatus = 1
        lcReturn = [anderes        ]    && Other
    CASE oPrinter.PrinterStatus = 2
        lcReturn = [unbekannt      ]    && Unknown
    CASE oPrinter.PrinterStatus = 3
        lcReturn = [bereit         ]    && Idle
    CASE oPrinter.PrinterStatus = 4
        lcReturn = [druckt         ]    && Printing
    CASE oPrinter.PrinterStatus = 5
        lcReturn = [aufwärmen      ]    && Warming Up
    CASE oPrinter.PrinterStatus = 6
        lcReturn = [gestoppt       ]    && Stopped Printing
    CASE oPrinter.PrinterStatus = 7
        lcReturn = [Offline        ]    && Offline
    CASE oPrinter.PrinterStatus = 8
        lcReturn = [pausierend     ]    && Paused
    CASE oPrinter.PrinterStatus = 9
        lcReturn = [Fehler         ]    && Error
    CASE oPrinter.PrinterStatus = 10
        lcReturn = [beschäftigt    ]    && Busy
    CASE oPrinter.PrinterStatus = 11
        lcReturn = [nicht verfügbar]    && Not Available
    CASE oPrinter.PrinterStatus = 12
        lcReturn = [wartend        ]    && Waiting
    CASE oPrinter.PrinterStatus = 13
        lcReturn = [verarbeiten    ]    && Processing
    CASE oPrinter.PrinterStatus = 14
        lcReturn = [initialisieren ]    && Initialization
    CASE oPrinter.PrinterStatus = 15
        lcReturn = [Stromsparmodus ]    && Power Save
    CASE oPrinter.PrinterStatus = 16
        lcReturn = [löscht Druckjob]    && Pending Deletion
    CASE oPrinter.PrinterStatus = 17
        lcReturn = [E/A aktiv      ]    && I/O Active
    CASE oPrinter.PrinterStatus = 18
        lcReturn = [manuelle Zufuhr]    && Manual Feed
    ENDCASE 
    * // Die Liste ggf. nach Bedarf erweitern
    IF INLIST(oPrinter.PrinterStatus,1,9)
        lcReturn = lcReturn + GetDetectedErrorStateAsText(oPrinter.DetectedErrorState)
    ENDIF 
    RETURN lcReturn
    
ENDFUNC 

* // ----------------------------------- GetDetectedErrorStateAsText
FUNCTION GetDetectedErrorStateAsText as String
LPARAMETERS vErrorstate as Integer 

    LOCAL lcReturn as String 
    
    DO CASE
    CASE m.vErrorState = 0
        lcReturn = [Unbekannter Fehler]                 && Unknown
    CASE m.vErrorState = 1
        lcReturn = [Anderer Fehler]                     && Other
    CASE m.vErrorState = 2
        lcReturn = [kein Fehler]                        && No Error
    CASE m.vErrorState = 3
        lcReturn = [zu wenig Papier]                    && Low Paper
    CASE m.vErrorState = 4
        lcReturn = [kein Papier]                        && No Paper
    CASE m.vErrorState = 5
        lcReturn = [zu wenig Toner]                     && Low Toner
    CASE m.vErrorState = 6
        lcReturn = [kein Toner]                         && No Toner
    CASE m.vErrorState = 7
        lcReturn = [Gehäuse geöffnet]                   && Door Open
    CASE m.vErrorState = 8
        lcReturn = [Papierstau]                         && Jammed
    CASE m.vErrorState = 9
        lcReturn = [Kundendienst erforderlich]          && Service Requested
    CASE m.vErrorState = 10
        lcReturn = [Ausgabeschacht ist voll]            && Output Bin Full
    CASE m.vErrorState = 11
        lcReturn = [Papier Problem]                     && Paper Problem
    CASE m.vErrorState = 12
        lcReturn = [Seite kann nicht gedruckt werden]   && Cannot Print Page
    CASE m.vErrorState = 13
        lcReturn = [Benutzereingriff notwendig]         && User Intervention Required
    CASE m.vErrorState = 14
        lcReturn = [Arbeitsspeicher voll]               && Out Of Memory
    CASE m.vErrorState = 15
        lcReturn = [unbekannter Server]                 && Server Unknown
    OTHERWISE
        lcReturn = [Unbekannt]    
    ENDCASE
    RETURN     [(] + ALLTRIM(STR(m.vErrorState)) + [) ] + lcReturn
    
ENDFUNC 

Keine Kommentare:

Kommentar veröffentlichen