@James_007 wrote:
Hallo PDFCreator-Freunde,
ich nutze die COMWrapper.dll für mein VB.net-Projekt. Alles läuft wunderbar. Nur wenn ich ein weiteres mal eine PDF-Datei konvertieren möchte, erhalte ich die Fehlermeldung, dass nur eine Instanz erlaubt sei. In dem Forum gesucht und gefunden: Nutze nun IsInstanceRunning(), wenn die diese True zurückgibt Kill ich die Prozesse die "PDFCreator" lauten.
Ich finde das keine schöne Lösung. Wäre es möglich, die bereits gestartete Instanz zu übernehmen?
Bei dem Kill-Vorgang habe ich außerdem das Problem, dass er teilweise die Queue nicht mehr prüft, obwohl was gedruckt wurde; es kommt ein Timeout-Fehler. Wenn man es anschließend nochmal versucht, funktioniert mein Programmablauf wieder.
Hier mein Code:
[PDFPrinting]Imports System.Runtime.InteropServices Imports pdfforge.PDFCreator.UI.ComWrapper Namespace PDF ''' <summary> ''' Enthält Methoden, um eine PDF Datei zu drucken. ''' </summary> Public Class PDFPrinting Implements IDisposable Private _settings As PDFSettings = Nothing Private _queue As Queue = Nothing ''' <summary> ''' Gibt zurück, ob min. 1 PDF-Drucker installiert ist, welcher ''' verwendet werden kann. ''' </summary> ''' <returns><c>True</c> wenn min. 1 verwendbarer PDF-Drucker installiert ist; <c>False</c> andernfalls.</returns> Public ReadOnly Property PDFPrinterInstalled As Boolean Get Return IsPDFPrinterInstalled() End Get End Property ''' <summary> ''' Gibt die Einstellungen zurück, welche für den Druck gelten sollen. ''' </summary> ''' <returns></returns> Public ReadOnly Property PDFEinstellungen As PDFSettings Get Return _settings End Get End Property ''' <summary> ''' Erstellt eine neue Instanz, um PDF-Dateien zu drucken. ''' </summary> Public Sub New() Me.Init() End Sub ''' <summary> ''' Wartet auf einen Druckauftrag in der Warteschlange und ''' wandelt den ersten Druckauftrag, welche auftritt in eine PDF-Datei um. ''' </summary> ''' <param name="FullPath">Vollständiger Pfad inkl. Dateiname, wo die Datei gespeichert werden soll.</param> ''' <exception cref="PDFException">Wenn ein Fehler auftritt beim Umwandeln.</exception> ''' <exception cref="TimeoutException">Wenn nach 15 Sekunden kein Druckauftrag in der Warteschlange eingegangen ist.</exception> ''' <remarks> ''' Befindet sich nicht innerhalb 15 Sekunden der Druckauftrag in der Warteschlange, wird der ''' Vorgang abgebrochen und eine Exception geworfen. ''' </remarks> Public Sub ConvertToPDF(ByVal FullPath As String) 'Variablendeklaration Dim job As PrintJob = Nothing Try 'Auf Druckjob in der Warteschlange warten If _queue.WaitForJob(15) = False Then Throw New TimeoutException("Es konnte kein Druckauftrag in der Warteschlange festgestellt werden. Vorgang abgebrochen.") Else 'Druckauftrag wurde in der Warteschlange empfangen 'Diesen übernehmen wir nun job = _queue.NextJob 'Einstellungen übernehmen job.SetProfileByGuid("DefaultGuid") For Each s As KeyValuePair(Of String, String) In _settings.GetSettings() job.SetProfileSetting(s.Key, s.Value) Next 'Umwandeln starten job.ConvertTo(FullPath) 'Umwandeln erfolgreich beendet? If (Not job.IsFinished Or Not job.IsSuccessful) Then Throw New PDFException("Der Druckjob konnte nicht in eine PDF-Datei umgewandelt werden. Der Auftrag war fehlerhaft oder nicht abgeschlossen.") End If End If Catch ex As Exception 'PDF-Exception als Wrapper werfen. Throw New PDFException("Fehler beim Umwandeln in eine PDF-Datei. " & ex.Message, ex) Finally 'Variablen wieder freigeben, weil COM-Objekt job = Nothing End Try End Sub ''' <summary> ''' Fügt einen Druckauftrag einer bestehenden PDF-Datei hinzu. ''' </summary> ''' <param name="PDFFile">Bestehende PDF-Datei, an welche eine weitere Seite hinzugefügt werden soll.</param> ''' <exception cref="PDFException">Wenn beim Hinzufügen der Seite ein Fehler auftritt.</exception> ''' <exception cref="TimeoutException">Wenn nach 15 Sekunden der Druckauftrag nicht im Spooler ist.</exception> Public Sub AddToExistsPDF(ByVal PDFFile As String) Me.AddToExistsPDF(PDFFile, 1) End Sub ''' <summary> ''' Fügt mehrere Druckaufträge zu einer bestehenden PDF-Datei hinzu. ''' </summary> ''' <param name="PDFFile">Bestehende PDF-Datei, an welche weitere Seiten hinzugefügt werden soll.</param> ''' <param name="CountJobs">Anzahl der Druckaufträge, auf welche gewartet werden soll.</param> ''' <exception cref="PDFException">Wenn beim Hinzufügen der Seiten ein Fehler auftritt.</exception> ''' <exception cref="TimeoutException">Wenn nach 15 Sekunden nicht die Anzahl an Druckaufträgen eingegangen ist.</exception> Public Sub AddToExistsPDF(ByVal PDFFile As String, ByVal CountJobs As Integer) End Sub ''' <summary> ''' Wartet auf eine gewisse Anzahl Druckaufträge in der Warteschlange und ''' wandelt alle Druckaufträge um in eine PDF-Datei. ''' </summary> ''' <param name="FullPath">Vollständiger Pfad, inkl. Dateiname, wo die Datei gespeichert werden soll.</param> ''' <param name="CountJobs">Anzahl der Druckaufträge, auf welche gewartet werden soll.</param> ''' <exception cref="PDFException">Wenn ein Fehler auftritt beim Umwandeln.</exception> ''' <exception cref="TimeoutException">Wenn nach 15 Sekunden nicht die Anzahl an Druckaufträgen eingegangen ist.</exception> ''' <remarks> ''' Befinden sich nicht innerhalb 15 Sekunden alle Druckaufträge in der Warteschlange, wird ''' der Vorgang abgebrochen und eine Exception geworfen. ''' </remarks> Public Sub MergeToPDF(ByVal FullPath As String, ByVal CountJobs As Integer) 'Variablendeklaration Dim job As PrintJob = Nothing Try 'Auf Druckjob in der Warteschlange warten If _queue.WaitForJobs(CountJobs, 15) = False Then Throw New TimeoutException("Es wurden nicht alle nötigen Druckaufträge in der Warteschlange festgestellt. Vorgang abgebrochen.") Else 'Druckauftrag wurde in der Warteschlange empfangen 'Diesen übernehmen wir nun _queue.MergeAllJobs() job = _queue.NextJob 'Einstellungen übernehmen job.SetProfileByGuid("DefaultGuid") For Each s As KeyValuePair(Of String, String) In _settings.GetSettings() job.SetProfileSetting(s.Key, s.Value) Next 'Umwandeln starten job.ConvertTo(FullPath) 'Umwandeln erfolgreich beendet? If (Not job.IsFinished Or Not job.IsSuccessful) Then Throw New PDFException("Der Druckjob konnte nicht in eine PDF-Datei umgewandelt werden. Der Auftrag war fehlerhaft oder nicht abgeschlossen.") End If End If Catch ex As Exception 'PDF-Exception als Wrapper werfen. Throw New PDFException("Fehler beim Umwandeln in eine PDF-Datei.", ex) Finally 'Variablen wieder freigeben, weil COM-Objekt job = Nothing End Try End Sub ''' <summary> ''' Initialisiert das PDF-Drucken. ''' </summary> Private Sub Init() 'Variablendeklaration Dim queueType As Type = Nothing Try 'Default-Einstellungen _settings = New PDFSettings() 'Wenn bereits eine Instanz läuft, killen wir den Prozess 'Denn eigentlich sollte vom PDF-Creator gar nichts laufen. If Me.IsInstanceRunning() = True Then For Each proc As Process In Process.GetProcessesByName("PDFCreator") proc.Kill() Next 'Drei Sekunden warten, bis wirklich alle Dienste beendet sind Threading.Thread.Sleep(3000) End If 'Queue initialisieren _queue = New Queue() _queue.Initialize() Catch ex As Exception Throw New PDFException("Fehler beim Initialisieren des PDF-Druckers. " & "PDF-Creator ist nicht installiert oder die COM-Schnittstelle registriert. " & "Bitte installieren Sie die Anwendung erneut. Fehlermeldung: " & ex.Message, ex) End Try End Sub ''' <summary> ''' Gibt zurück, ob bereits eine Instanz von PDFCreator läuft. ''' </summary> ''' <returns><c>True</c>, wenn bereits eine Instanz läuft; <c>False</c> andernfalls.</returns> Private Function IsInstanceRunning() As Boolean 'Variablendeklaration Dim pdfobj As PdfCreatorObj = Nothing Try pdfobj = New PdfCreatorObj() Return pdfobj.IsInstanceRunning Catch ex As Exception Throw New PDFException("Fehler beim prüfen, ob PDFCreater-Instanz bereits läuft. " & ex.Message) Finally 'PDF-Objekt freigeben pdfobj = Nothing End Try End Function ''' <summary> ''' Gibt den Drucker-Namen zurück, welcher für diesen PDF-Druck ''' geeignet ist. ''' </summary> ''' <returns>Namen des installierten und verwendbaren PDF-Druckers</returns> ''' <exception cref="PDFException">Wenn ein Fehler beim Ermitteln des Druckers auftritt oder kein Drucker installiert ist.</exception> Public Shared Function GetPDFPrinter() As String 'Variablendeklaration Dim PDFCreator As PdfCreatorObj = Nothing 'Wurde ein Drucker installiert? If IsPDFPrinterInstalled() = False Then Throw New PDFException("Es ist kein PDF-Drucker installiert. Bitte installieren Sie die Anwendung erneut.") End If Try 'Instanz von PDF-Creator erzeugen PDFCreator = New PdfCreatorObj() 'Wir nehmen den ersten immer zu findenden Drucker! 'Aufgrunddessen, weil wir bereits geprüft haben, ob überhaupt ein 'Drucker installiert ist, können wir hier gleich auf den Index losgehen. Return PDFCreator.GetPDFCreatorPrinters.GetPrinterByIndex(0) Catch ex As Exception 'PDF-Exception als Wrapper werfen. Throw New PDFException("Der PDF-Drucker konnte nicht ermittelt werden.", ex) Finally 'PDF-Creator Instanz freigeben. PDFCreator = Nothing End Try End Function ''' <summary> ''' Prüft, ob PDF-Creator installiert ist und ob min. 1 ''' PDF-Drucker verfügbar ist. ''' </summary> ''' <returns><c>True</c> wenn PDF-Creator installiert ist und min. 1 Drucker verfügbar ist; <c>False</c> andernfalls.</returns> Private Shared Function IsPDFPrinterInstalled() As Boolean 'Variablendeklaration Dim PDFCreator As PdfCreatorObj = Nothing Try PDFCreator = New PdfCreatorObj() If PDFCreator.GetPDFCreatorPrinters.Count > 0 Then Return True End If Return False Catch ex As Exception Console.WriteLine("Ausnahme bei PDF-Drucker installiert: {0}", ex.Message) Return False Finally PDFCreator = Nothing End Try End Function #Region "IDisposable Support" Private disposedValue As Boolean ' Dient zur Erkennung redundanter Aufrufe. ' IDisposable Protected Overridable Sub Dispose(disposing As Boolean) If Not disposedValue Then If disposing Then If _queue IsNot Nothing Then _queue.ReleaseCom() End If 'Prüfen ob der Prozess noch läuft und dann abwürgen For Each proc As Process In Process.GetProcessesByName("PDFCreator") proc.Kill() Next End If _queue = Nothing _settings = Nothing End If disposedValue = True End Sub ' Dieser Code wird von Visual Basic hinzugefügt, um das Dispose-Muster richtig zu implementieren. Public Sub Dispose() Implements IDisposable.Dispose ' Ändern Sie diesen Code nicht. Fügen Sie Bereinigungscode in Dispose(disposing As Boolean) weiter oben ein. Dispose(True) End Sub #End Region End Class End Namespace
[Aufruf]
'Ist die Datei bereits eine PDF? If IO.Path.GetExtension(org_dateiname).ToLower().Equals(".pdf") = True Then 'Es handel sich bereits um eine PDF-Datei. 'Die schreiben wir einfach da hin, wo der Anwender sie hinhaben will. Utilities.FileSystem.Dateien.WriteStreamToFile(dbAkten.GetDokument(aktendatei_id), filename, True) Else 'Datei im TempPfad speichern Utilities.FileSystem.Dateien.WriteStreamToFile(dbAkten.GetDokument(aktendatei_id), tempFile, True) 'Es ist keine PDF! Wir müssen die Datei mit dem Standard-Programm 'öffnen und dann versuchen zu drucken proc = New Process() With { .StartInfo = New ProcessStartInfo(tempFile) With { .Verb = "printto", .WindowStyle = ProcessWindowStyle.Hidden, .Arguments = Utilities.PDF.PDFPrinting.GetPDFPrinter() } } proc.Start() proc.WaitForExit(60000) 'PDF-Datei erzeugen Using pdf As New Utilities.PDF.PDFPrinting() pdf.ConvertToPDF(filename) End Using End If
Posts: 1
Participants: 1