[Brainstorm] PrintSpooler-Überwachung (C#) - Laufzeitproblem
-
Hi,
Situation:
DB mit ca 200 Dokument-Pfaden auf lokalen/Netzwerklaufwerken (alles PDF)
Aufgabe:Sicherstellen das jedes gedruckt wird
Ansatz:
Threaded PrintSpooler-Watcher mit hoher Priorisierung der ständig via ManagementObjectSercher und "SELECT * FROM Win32_PrintJob" die Liste der aktuellen Druckjobs pollt, die des gewünschten Druckers filtert, Dokumentname und ID ausliest und als string in ein HashSet wegspeichert - das aktuelle wird gegen das letzte HashSet verrechnet
HashSet<string> noLongerIn = new HashSet<string>( LastRunsSpoolerContent ); noLongerIn.ExceptWith( currentSpoolerContent ); HashSet<string> newlyIn = new HashSet<string>( currentSpoolerContent ); newlyIn.ExceptWith( LastRunsSpoolerContent );
und per delegates werden die Rein/Raus HashSets an das "Drucker-Prog" weitergereicht - welcher die dann speichert.
Das eigentliche "Drucker-Prog" holt sich alle Pfade aus der DB (prüft ob Datei vorhanden, sortiert etwas vor , usw). Es wartet Anfänglich bis der Spooler mal leer ist, druckt dann via
Process proc = new Process(); proc.StartInfo.Verb = "print"; // ( == AcrobatReader ) proc.StartInfo.FileName = fullPathPrintFile; proc.Start(); proc.CloseMainWindow(); proc.Close();
eine Datei, wartet bis der SpoolerWatcher sie detektiert (rein), wartet bis sie als Raus gemeldet wird und nimmt dann (optimistisch) an es sei Gedruckt - wartet wieder bis Druckerspooler leer, usw.
Wenn der Drucker dann auf einen Fehler läuft muss man nur max. das letzte Dokument neu drucken - Status in der DB wird entsprechend angepasst und bisserl drumrum. Wird ein Dokument NICHT mit Rein/Raus detektiert bricht das "Druck-Prog" ab - (Papier/Toner alle, Drucker disconnected, andere Druckjobs blockieren ihn, usw.).
Problem:
Bei kleinen PDFs (das letzte hatte um 60kb) kann es passieren dass der SpoolerWatcher es nicht detektiert da es in der Zeit der HashSet-Buildung/Delegate aufrufe "durchflutscht" -> was dann zum Abbruch des "Drucker-Prog"'s führt obwohl es gedruckt wurde - schlimmer ist das das Dok dann auch nicht in der DB geflagged wird und wieder und wieder versucht wird zu drucken - wobei es uU wieder durchflutscht usw.
(Verworfene Ansätze:
Abfrage der Drucker/Statie mittels WMI tut wg. inkompatiblem Drucker nicht
über Systems.Printing.PrintServer(), wegen Bug in der statischen Methode die die Drucker holt (siehe http://social.msdn.microsoft.com/Forums/en/winforms/thread/04d04890-0931-4ef0-aa79-02e9582bb806) und irgendwann beim Disposen zuschlägt
Jemand ne Idee? Gitbs Irgendwie einen Weg sich auf Events "Neues Dokument in Druckerspooler" zu registrieren um von dem blöden Pollig weg zu kommen?
In jedes PDF ein 1000mb Tiff einzubetten ist keine valide Lösung
-
...
-
Du müsstest nur mal ein bisschen suchen, dann würdest du schon was finden. Zum einen haben verschiedene Leute schon ähnliche Probleme gehabt mit dem Drucken von PDF Files. Geh mal auf stackoverflow.com oder such in der MSDN (da ist Stackoverflow gleich inbegriffen).
Und man kann einen Print-Spooler mit der WinAPI überwachen:
http://msdn.microsoft.com/en-us/library/windows/desktop/dd162722.aspxÜber P/Invoke kannst du dies daher auch in C# verwenden. Gibt allerdings auch fertige Bibliotheken. Auf Anhieb habe ich z.b. das hier gefunden:
http://printqueuewatch.codeplex.com/Grüssli
-
Bsher bin ich ohne PInvoke ausgekommen, danke für den Denkanstoss
Ich fand den Beitrag hier bzgl Interop: http://msdn.microsoft.com/en-us/magazine/cc164123.aspx
Da die FindFirstPrinterChangeNotification einen HANDLE erwartet muss ich wohl zumindest
- OpenPrinter
- ClosePrinter
- FindNextPrinterChangeNotification
- FindClosePrinterChangeNotificationmappen - zusätzlich noch EnumJobs um an den Pfad zu kommen und zu schauen ob es eines 'meiner' Dokumente ist - 'Can of Worms, anyone?'
zusätzlich anbinden. Für mich reicht wohl
PRINTER_CHANGE_ADD_JOB + PRINTER_CHANGE_DELETE_JOB
aus da ich nur am Eintritt / Verlassen von Jobs in die Queue interessiert bin.--
Eigentlich hatte ich eher in Richtung System.Management.ManagementEventWatcher gehofft (http://msdn.microsoft.com/en-us/library/z8ay9bxx.aspx)
.. nur statt Win32_Process Win32_PrintJob (geht das?) und mit ner Polltime von TimeSpan.FromTicks(1) ohne Polling-Timeout ... oder aber ohne Polltime, muss mal sehen, wie die da ein Event drankoppeln - die API ist in der Hinsicht (genauso wie beim Konstruieren der Queries) etwas schwammig - oder ich hab noch nicht die richtige Seite gefunden.
Auf jeden Fall ein Tip zum Suchen und rumspielen, thx.
-
Mit WMI kenne ich mich leider zu wenig aus. Allerdings gibt es da glaub ich auch irgendwelche Events und co. Am besten schaust du da vielleicht mal bei stackoverflow.com nach, falls sich hier niemand finden lässt.
Grüssli