Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
PDF Dokumente aus C# heraus drucken
Gelöschter Benutzer

PDF Dokumente aus C# heraus drucken

beantworten | zitieren | melden

Hallo, gibt es eine Möglichkeit, PDF-Dokumente ohne installierten Adobe-Reader auf einem Standardrucker auszudrucken?

Oder gibt es für den Adobe Reader APIs? Oder muss man das ganze irgendwie über die CMD-Shell anhand eines Prozessaufrufs mittels der Adobe.exe zusammenbasteln?

Wenn möglich möchte ich "nur" mit C# Mitteln und Adobe.exe arbeiten, ohne Opensource-Bibliotheken.
Ploetzi
myCSharp.de - Member

Avatar #avatar-2940.gif


Dabei seit:
Beiträge: 313

beantworten | zitieren | melden

Das ganze sollte ganz einfach gehn
Der Batch befehl wuerde wie folgt aussehen:
c:\Program files\AdobeAcrobat 7.0\Reader\acrord32.exe /t c:\test.pdf

Das ganze kannst du dann mit Process.Start(...starten.

Ein beispiel zu System.Process.Start findest du hier.
private Nachricht | Beiträge des Benutzers
Rainbird
myCSharp.de - Experte

Avatar #avatar-2834.jpg


Dabei seit:
Beiträge: 3.728
Herkunft: Mauer

beantworten | zitieren | melden

Zitat von gijoe222
Oder gibt es für den Adobe Reader APIs?
Der Reader installiert automatisch ein ActiveX-Steuerelement. Das kannst Du direkt in Deiner Anwendung aufrufen und alle Funktionen wie Drucken etzc. direkt ansprechen. Du musst das Steuerelement als COM-Verweis hinzufügen (heißt glaube ich "Adobe Acrobat Control" oder so ähnlich).
private Nachricht | Beiträge des Benutzers
Jelly
myCSharp.de - Member



Dabei seit:
Beiträge: 1.114
Herkunft: Burden (Luxemburg)

beantworten | zitieren | melden

Zitat von Rainbird
Der Reader installiert automatisch ein ActiveX-Steuerelement.
Wobei aber peinlichst auf die Acrobatversion zu achten ist. Wenn der Zielrechner eine andere Acrobat Version installiert hat wie dein Entwicklungsrechner, schlägts fehl.

Eine Alternative zu Acrobat ist GPrint.exe, die in Ghostscript und Ghostview enthalten ist. Ist, finde ich, wesentlich schlanker als ein Acrobat Reader, und auch schneller beim Drucken. Über verschiedene Commandline Parameter können noch unterschiedliche Druckoptionen definiert werden: Druckername, Anzahl Kopien usw.
private Nachricht | Beiträge des Benutzers
Ploetzi
myCSharp.de - Member

Avatar #avatar-2940.gif


Dabei seit:
Beiträge: 313

beantworten | zitieren | melden

jop oder eben das acrobat ueber die commandline ansteuern ist sicher auch nicht kritisch mit der versionierung
private Nachricht | Beiträge des Benutzers
norman_timo
myCSharp.de - Member

Avatar #avatar-1775.jpeg


Dabei seit:
Beiträge: 4.506
Herkunft: Wald-Michelbach (Odw)

beantworten | zitieren | melden

Hallo zusammen,

die Quizfrage war doch:
Zitat
PDF-Dokumente ohne installierten Adobe-Reader auf einem Standardrucker auszudrucken?

Und dazu kann ich nur sagen, wahrscheinlich geht das nicht. Es gibt diverse (auch kostenlose) PDF-Drucker, diese richten sich als Drucker ein und produzieren eine PDF Datei, das ist aber in Deinem Fall nicht gewünscht, weil es ja nicht der Standarddrucker ist und die Datei dann immer noch nicht gedruckt ist.

Jelly hat hier für diesen Fall eine gute Alternative genannt, aber auch die muss installiert werden:
Zitat
Eine Alternative zu Acrobat ist GPrint.exe, die in Ghostscript und Ghostview enthalten ist. Ist, finde ich, wesentlich schlanker als ein Acrobat Reader, und auch schneller beim Drucken. Über verschiedene Commandline Parameter können noch unterschiedliche Druckoptionen definiert werden: Druckername, Anzahl Kopien usw.

Grüße
Norman-Timo
A: “Wie ist denn das Wetter bei euch?”
B: “Caps Lock.”
A: “Hä?”
B: “Na ja, Shift ohne Ende!”
private Nachricht | Beiträge des Benutzers
Gelöschter Benutzer

beantworten | zitieren | melden

Die Software wird vermutlich später kommerziell benutzt, bzw. verkauft. Deshalb kann/möchte ich nicht "irgendwelche" Programme in Anspruch nehmen. Der Adobe Reader wäre die einzige Ausnahme, da der schon praktisch überall installiert ist.

Falls ich es mit einem Batchbefehl geht, wie kann ich das Pfad- und Versionsunabhängig machen? Damit das auch wirklich auf jedem PC läuft (XP, VIsta, Adobeversion 7,8,9..), und das, auch wenn kein User angemeldet ist?

PS: Habe in der Konsole mal den Befehl abgesetzt: ...\Reader\acrord32.exe /t c:\test.pdf , da geht bei mir nur der Reader auf, ohne Printbefehl o.ä. Ich habe die Version 9. Haben die Switchs geändert oder mach ich was falsch?

PS2: Ich google gerade nach Adobe-Apis. Kann ich evtl mit dem Adobe Acrobat SDk 8.0 etwas machen?
Dieser Beitrag wurde 3 mal editiert, zum letzten Mal am .
Rainbird
myCSharp.de - Experte

Avatar #avatar-2834.jpg


Dabei seit:
Beiträge: 3.728
Herkunft: Mauer

Versionsunabhängig

beantworten | zitieren | melden

Du kannst das auch mit dem ActiveX-Control versionsunabhängig machen. Der Schlüssel dazu ist die Klasse AxHost im Namensraum System.Windows.Forms. Damit kann man ganz einfach ohne Interop-Verweise ActiveX-Controls hosten. Du benötigst nur die CLSID, welche bei allen Acrobat-Versionen gleich ist. Nur die 64-Bit Varianten haben eine andere CLSID. Also eine CLSID für 32 Bit und eine für 64 Bit.

Die CLSID kannst Du heruasfinden, indem Du in der Registry nach der ProgId des ActiveX-Controls suchst.
private Nachricht | Beiträge des Benutzers
Gelöschter Benutzer

beantworten | zitieren | melden

@Rainbird: Das wäre toll. Ich habe noch nie ActiveX aus C# angesteurt... werds aber versuchen. Beispielcode wäre natürlich toll;)

So, geh mal schlafen. Das ausdrucken von PDFs scheint ja wirklich nicht trivial zu sein...
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal am .
Gelöschter Benutzer

beantworten | zitieren | melden

Die ProgID habe ich, wie weiter?
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal am .
Rainbird
myCSharp.de - Experte

Avatar #avatar-2834.jpg


Dabei seit:
Beiträge: 3.728
Herkunft: Mauer

AxHost

beantworten | zitieren | melden

Hallo gijoe222,

da sowas schon öfter gefragt worden ist, habe ich ein kleines Beispiel-Projekt unter Adobe Reader ActiveX ohne Interop-Verweis versionsunabhängig in Windows.Forms hosten gepostet.

Das Drucken ist schon trivial. Im einfachsten Fall ist es eine Zeile Code:


/// <summary>
    /// .NET Wrapper für Adobe Reader ActiveX-Steuerelement
    /// </summary>
    public class AdobeReaderControl : AxHost
    {
        /// <summary>
        /// Hostet das Adobe Reader ActiveX-Steuerelement in Windows.Forms.
        /// </summary>
        public AdobeReaderControl()
            : base("{CA8A9780-280D-11CF-A24D-444553540000}") // CLSID des Adobe Readers (ist bei allen 32-Bit Versionen gleich)
        {}

        ...

        /// <summary>
        /// Druckt die geladene PDF-Datei.
        /// </summary>
        public void Print()
        {
            // Print-Methode auf dem Adobe Reader aufrufen
            this.GetOcx().GetType().InvokeMember("Print", BindingFlags.InvokeMethod | BindingFlags.OptionalParamBinding, null, this.GetOcx(), new object[0] );
        }
    }
private Nachricht | Beiträge des Benutzers
Gelöschter Benutzer

beantworten | zitieren | melden

Hey coool! Besten Dank für das Posten dieses Codes!
tikra
myCSharp.de - Member

Avatar #avatar-3196.png


Dabei seit:
Beiträge: 185

beantworten | zitieren | melden

Wenn ich die Prozessvariante mit bestimmten Parametern wähle, stoße ich auf 2 Probleme:

- Das Konsolenfenster taucht auf, obwohl ich die Anweisung gebe, dass kein Fenster erscheinen soll.

- Wenn ich nicht auf einem physikalischen Drucker drucke, sondern auf einem PDF-Drucker, dann wird die Codeabarbeitung direkt nach dem Starten des Prozesses weitergeführt. Gibt es eine Möglichkeit, mit der Abarbeitung zu warten? WaitForExit() scheint nicht die ultimative Lösung zu sein.

Wenn ich nach dem Starten des Prozesses File.Move (Umbennen) auf den erstellten File mache, wird eine Exception geworfen, dass auf die Datei nicht zugegriffen werden kann.

Hatte jemand schon einmal ähnliche Probleme und evtl. Lösungen zu diesen beiden Problemen?
private Nachricht | Beiträge des Benutzers
Rainbird
myCSharp.de - Experte

Avatar #avatar-2834.jpg


Dabei seit:
Beiträge: 3.728
Herkunft: Mauer

Prozessvariante

beantworten | zitieren | melden

Hallo timmi,

für eine weitreichende Automatisierung ist die Prozessvariante nicht die beste Wahl. Du solltest stattdessen das COM-Objektmodell der Adobe Produkte nutzen. Damit hast Du über alles die volle Kontrolle (Sichtbarkeit, Drucken etc. ).

So kannst Du auch eine Anwendungsinstanz des Adobe Readers (bzw. Acrobat Professional) fernsteuern.

Eine Frage noch: Warum willst Du ein PDF auf einem PDF-Drucker ausdrucken? Das ergibt für mich keinen Sinn.
private Nachricht | Beiträge des Benutzers
tikra
myCSharp.de - Member

Avatar #avatar-3196.png


Dabei seit:
Beiträge: 185

beantworten | zitieren | melden

Von der COM-Variante wurde doch abgeraten, weil so "peinlichst genau" auf die Version geachtet werden muss oder?

Auf der anderen Seite: Kann man den Verweis nicht lokal mit kopieren und dann sogar ohne eine Adobe-Installation auskommen?

Wieso rätst du nicht (diese Variante hätte ich jetzt eher bevorzugt) zu deiner Lösung mit der CLSID?

________________________________________________________
Anderes Thema:
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯

Naja, 'tschuldigung: Genauer gesagt drucke ich auf einen Postscript-Drucker. Ein paar mal hintereinander. Und da dieser ja immer in die selbe Datei druckt, muss ich die Dateien nach einem Druckauftrag umbenennen, dies funktioniert aber ohne weiteres nicht, weil er eben ohne Verzögerung direkt zum File.Move springt, wobei die Datei noch "bedruckt" wird.

Ich hab dieses Problem so gelöst:

                                                PrintPS(Dokument[i]);

                                                while (!File.Exists(File))
                                                    Thread.Sleep(2000);
                                                Thread.Sleep(2000);

Ich finde diese Lösung allerdings sehr unbefriedigend, auch wenn Zeit eigentlich eher weniger eine Rolle spielt... es ist einfach alles andere als elegant... :(

Gibt es eventuell irgendwelche Events (tiefer in Windows drin) die man abfangen und erst beim Auslösen dieses Events mit der Abarbeitung fortfahren könnte?

Ich danke dir übrigens vielmals für deine Antwort! :)
Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von tikra am .
private Nachricht | Beiträge des Benutzers
tikra
myCSharp.de - Member

Avatar #avatar-3196.png


Dabei seit:
Beiträge: 185

beantworten | zitieren | melden

Hat niemand eine Idee zu diesem Problem?
private Nachricht | Beiträge des Benutzers
mosspower
myCSharp.de - Member

Avatar #avatar-2662.jpg


Dabei seit:
Beiträge: 452
Herkunft: Bamberg

beantworten | zitieren | melden

Ich möchte mal den Thread wieder öffnen, da ich aktuell das gleiche Problem habe. Ich würde gerne eine laufende Lösung mittels GPrint.exe mit einer API-Variante ersetzen.

Nun ist ja wieder eine Zeit lang vergangen - deshalb wollte ich hier mal nachfragen, ob es mittlerweile nicht andere Lösungen gibt?

Vielen Dank schon einmal im Voraus für eure Antworten
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von mosspower am .
private Nachricht | Beiträge des Benutzers
Joetempes
myCSharp.de - Member

Avatar #avatar-3309.jpg


Dabei seit:
Beiträge: 888
Herkunft: Germany

beantworten | zitieren | melden

Ich mach das aktuell so:


/// <summary>
        /// Druckt ein PDF Dokument 
        /// </summary>
        /// <param name="path">Pfad zum Dokument</param>
        public static void PrintPDFFile(string path)
        {
            FileInfo fileInfo = new FileInfo(path);
            if(!fileInfo.Exists)
            {
                throw new FileNotFoundException();
            }

            int id = 0;

            try
            {
                using(Process proc = new Process())
                {
                    proc.StartInfo.Verb = "print";
                    proc.StartInfo.FileName = path;
                    proc.StartInfo.CreateNoWindow = true;
                    proc.StartInfo.UseShellExecute = true;
                    proc.StartInfo.ErrorDialog = true;
                    proc.Start();

                    id = proc.Id;
                    proc.WaitForExit(10000);
                }
            }
            catch
            {
                //IGNORE 
            }
            finally
            {
                HelperUtils.killProcessById(id);
            }
        }

        /// <summary>
        /// Beendet einen Prozess an Hand seiner Id
        /// </summary>
        /// <param name="id">ProcessId</param>
        private static void killProcessById(int id)
        {
            foreach(Process p in Process.GetProcesses())
            {
                if(p.Id == id)
                {
                    p.Kill();
                    break;
                }
            }
        }
private Nachricht | Beiträge des Benutzers
mosspower
myCSharp.de - Member

Avatar #avatar-2662.jpg


Dabei seit:
Beiträge: 452
Herkunft: Bamberg

beantworten | zitieren | melden

@Joetempes,

sollte aber nur dann gehen, wenn Adobe installiert ist, und genau das dauert dann eben ewig, weil im Hintergrund die Standardprozesse verwendet werden.

Ist zwar schon wieder über 1 Jahr her, aber ich denke, ohne Kohle zu investieren, ist gprint die beste Lösung auf der .NET-Schiene und so läuft das auch jetzt produktiv.

Lass' mich aber gerne eines besseren belehren.
private Nachricht | Beiträge des Benutzers
Morloc
myCSharp.de - Member



Dabei seit:
Beiträge: 1

Einfach das Browserplugin nutzen

beantworten | zitieren | melden

Das allereinfachste und total unabhängig vom PDF Reader ist es, einfach das Webbrowsercontrol zu benutzen und auf die PDF Datei zu navigieren. Egal welcher PDF Viewer installiert ist, es wird auf das entsprechende Browser Plugin zurückgegriffen und die Datei wird angezeigt. Man muss sich mit keinem Lizenzproblem rumärgern, muss auf keine Versionen achten... es funktioniert einfach
private Nachricht | Beiträge des Benutzers
mosspower
myCSharp.de - Member

Avatar #avatar-2662.jpg


Dabei seit:
Beiträge: 452
Herkunft: Bamberg

beantworten | zitieren | melden

@Morloc,

für Massendruckaufträge imo nicht geeignet, da erhebliche Performanceprobleme ... da können die beim Konfektionieren Däumchen drehen ;) ... von Ansteuerung verschiedener Drucker via Threads ganz zu schweigen und usus ist es auch nicht, aus z.B. einem Service heraus ein (Browser) Controlelement zu instanzieren.
private Nachricht | Beiträge des Benutzers