eraser251105
Goto Top

Duplexmodus des Druckers auslesen

Hallo Gemeinde,

ich suche einen Weg, um den genauen Duplexmodus des Druckers auszulesen. Den Artikel von MS funktioniert leider nur bedingt.

Wir nutzen den API Call:

Private Declare Function SetPrinter Lib "winspool.drv" Alias _
"SetPrinterA" (ByVal hPrinter As Long, ByVal Level As Long, _
pPrinter As Byte, ByVal Command As Long) As Long

um den entsprechenden Modus zu setzen. (Bis Windows XP)
Da wir aber jetzt auf Windows 7 64Bit migrieren wollen, funktioniert dieser API Call nicht mehr sauber und setzt den Duplexmodus
bei 1 von 10 Dokumenten falsch.

Deswegen habe ich versucht das ganze über einen virtuellen Drucker zu machen, der eine Duplexeinheit besitzt. Ich habe mir hier
lokal 3 Dateien angelegt (simplex, duplexShortSide, duplexLongSide), die ich während der Laufzeit per RunDll32 laufen lasse und
dann dementsprechend den Modus ändere. Das funktioniert soweit. Nur wenn man mehrere Dokumente mit einmal ausdruckt und
während der Laufzeit den Modus ändert, habe ich das Gefühl, das unser Word das so schnell nicht mitbekommt, dass sich der Modus
des Druckers geändert hat.

Nun meine Frage:
Gibt es einen Weg (über WMI) außer bei W32_Printer die Eigenschaft "duplex", den ich nutzen kann, um beim aktiven Drucker den aktuellen
Duplexmodus herauszufinden. Also wie gesagt, die API Calls unter Win7 laufen nicht 100%.

Danke vorab für eure Antworten.

Content-Key: 170236

Url: https://administrator.de/contentid/170236

Ausgedruckt am: 28.03.2024 um 15:03 Uhr

Mitglied: Softprogger
Softprogger 22.07.2011 um 11:55:14 Uhr
Goto Top
Hallo Eraser,

mit der SetPrinter-Api hat das keinen Erfolg.
Stattdessen muß die Documentproperties-Api verwendet werden. Das ist zwar aufwendiger, geht dafür aber zu 100%

Dazu
1. mit OpenPrinter ein Handle auf den Drucker besorgen
2. mit Documentproperties den Devmode holen
3. aus der Devmode-Structure dmDuplex lesen ---> momentaner Duplexmodus
4. mit ClosePrinter das Druckerhandle schliessen

Soll der Duplexstatus geändert werden:
1. mit OpenPrinter ein Handle auf den Drucker besorgen
2. mit Documentproperties den Devmode holen
3. den ermittelten Devmode in eine leere Devmodestructure kopieren (also nur den öffentlichen Devmode-Bereich erfassen)
4. darin den gewünschten Duplexmode in dmDuplex setzen
5. in dmFlags das Bit DM_Duplex setzen
6. den Devmode zurückkopieren
7. Documentproperties mit DM_INBUFFER OR DM_OUTBUFFER aufrufen
8. ggfs. ResetDC aufrufen
9. mit ClosePrinter das Druckerhandle schliessen

Hoffe das hilft Dir weiter

Gruß Softprogger

3. aus der Devmode-Structure dmDuplex lesen ---> momentaner Duplexmodus
Mitglied: eraser251105
eraser251105 22.07.2011 um 13:04:46 Uhr
Goto Top
hi softprogger,

probier das heute mal aus und schreib dir dann, ob das geklappt hat.
Hast du auch negative Erfahrungen mit einigen API Calls unter Win7?
gruss
Mitglied: eraser251105
eraser251105 22.07.2011 um 13:52:40 Uhr
Goto Top
hi softprogger,

also ich habe das jetzt mal probiert und es funktioniert leider immer noch nicht zu 100%.

Ich nutze in VB6 folgende Schleife zum erzeugen der Dokumente:

Dim WordApp As Object
Dim doc As Object

Set WordApp = CreateObject("word.application")
Set doc = WordApp.Documents.Add
doc.range.Text = "Seite 1"

For I = 1 To 30
SetSimplex
WarteBisGesetztIst 1
doc.PrintOut False, , , Environ$("temp") & "\simplex" & CStr(I) & ".prn", printtofile:=True, collate:=True

SetLongSide
WarteBisGesetztIst 2
Call doc.PrintOut(False, , , Environ$("temp") & "\duplexLongSide" & CStr(I) & ".prn", printtofile:=True, collate:=True)

SetShortSide
WarteBisGesetztIst 3
Call doc.PrintOut(False, , , Environ$("temp") & "\duplexShortSide" & CStr(I) & ".prn", printtofile:=True, collate:=True)
Next
Debug.Print Timer
MsgBox "Fertig"


Funktion zum Setzen des Modus
Sub SetSimplex()
ShellAndWait "rundll32 printui.dll,PrintUIEntry /Sr /n " & """BKF-Drucker""" & " /a " & """C:\logfiles\simplex.dat""" & " u", vbHide
End Sub


Private Function WarteBisGesetztIst(ByVal v_Duplex As Byte)
Dim t0 As Single 'für den Timer
Dim nSecond As Integer
Dim o As Object
Dim Backup As Long
'Timer setzen und max. 10sek warten bis Simplex gesetzt ist
t0 = Timer
nSecond = 10
Do While Timer - t0 < nSecond
If GetPrinterDuplex(Printer.DeviceName, Printer.hdc) = v_Duplex Then Exit Do
Debug.Print "Noch nicht gesetzt"
DoEvents
' If we cross midnight, back up one day
If Timer < t0 Then
t0 = t0 - 24 * 60 * 60 ' or t0 = t0 - 86400
End If
Loop
Set o = Nothing

End Function


Wobei ich mit "GetPrinterDuplex" mir mit deinen Tip (Documentsproperties) den Duplexmodus hole.
Hast du einen weiteren Tip für mich?
gruss
eraser
Mitglied: Softprogger
Softprogger 22.07.2011 um 14:24:39 Uhr
Goto Top
Hi Eraser,

ich kann zwar keinen API-Code sehen, aber ich denke es fehlt das Resetten des PrinterDC's.
also nach dem Setzen der Dokumentproperties noch ResetDC(Handle,pDevmode), sonst verbleibt der Drucker auf seinem vohergehenden Status.
(In VB ist das Printerhandle fast immer offen!)

Diese Problematik betrifft nicht nur Windows7 (wobei es da hauptsächlich Pointerprobleme gibt...).
Früher habe ich auch mal solche Experimente unter VB6 gemacht. Dadurch bin ich mehr und mehr zu dem Stand gekommen, dass VB6 für das GUI einer App ganz interessant ist, aber wenn es ans 'Eingemachte' geht, sollte schon wegen der Performance mit den API's jongliert werden, und das nach Möglichkeit in einer eigenstämdigem DLL.
VB-Net hat sicherlich mehr Möglichkeiten, verliert aber noch mehr Performance, da über das Framework letztendlich auch nur API's über einen Wrapper zum Tragen kommen. So wird der Zuwachs an Hardwarepower oft schneller verheizt als man denkt.
Als Programmierer, der mit DOS und seinen beschränkten (Hardware-)Möglichkeiten groß geworden ist, tut es manchmal einfach weh, wie unachtsam mit Resourcen umgegangen wird.

Gruß
Softprogger
Mitglied: eraser251105
eraser251105 22.07.2011 um 16:28:33 Uhr
Goto Top
hi,
probier ich aus...
danke erstmal für deine Mühe...
gruss
eraser
Mitglied: eraser251105
eraser251105 25.07.2011 um 09:24:01 Uhr
Goto Top
Hi Softprogger,

ich habe es mal getestet mit folgenden Ergebnis.
Unter Windows XP werden 270 Dokumente sauber erzeugt. Ich habe ein Prüfroutine geschrieben, die jede einzelne Datei öffnet und schaut, ob die Druckdatei sauber mit dem
richtigen Modus erzeugt wurde (also bei Simplex=Duplex none, bei DuplexLongSide= Duplex NoTumple, bei DuplexShortSide=Duplex Tumble).
Da sind 270 prn Datei unter XP sauber erzeugt wurde.

Gleicher Vorgang unter Win7. Dateien werden erzeugt, dann gescannt und 160 Dateien sind fehlerhaft.

Hast du noch nen Tip?

Also, wie gesagt, ich brauche nur einen sauberen API Call, der mir den aktuellen Modus des virtuellen Drucker zurückgibt. Das Setzen läuft bei mir über die Dateien.
Gruss Eraser
Mitglied: eraser251105
eraser251105 25.07.2011 um 15:02:44 Uhr
Goto Top
Hi Softprogger,

ich denke, ich habe den Fehler jetzt eingegrenzt. Und zwar habe ich 2 verschiedene Office Versionen.
Office 2007 und Office 2010.

Beim System Windows XP --> Office 2007 funktioniert alles
Beim System Windows 7 --> Office 2007 funktioniert alles
Beim System Windows 7 --> Office 2010 funktioniert es nicht.

Jetzt habe ich mal geschaut, was die Unterschiede sind. Und zwar folgendes. Man hat bis Office 2007 nur die Möglichkeit beim Drucker
systemweit die Einstellungen zu setzen und diese Einstellungen gelten für alle Dokumente in der Word-Instanz, wobei die Druckereinstellungen
in Word 2010 (Office 2010) jeweils für das einzelne Dokument ist, dass heißt, dass unabhängig von der Systemeinstellungen des Druckers hier der DuplexModus für jedes einzelne
Dokument gesetzt werden kann. Das ist zwar, finde ich, eine Weiterentwicklung in Office, nur funktioniert deswegen unser Drucksystem nicht mehr.

Jetzt muss ich eine programmatische Lösung finden, um diese Duplexeinstellungen zur Laufzeit zu ändern.
Kennst du dich da aus?
gruss Eraser