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.
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.
Unsere Website
iPhone Programmierung | Android Programmierung
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).
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.
jop oder eben das acrobat ueber die commandline ansteuern ist sicher auch nicht kritisch mit der versionierung
Unsere Website
iPhone Programmierung | Android Programmierung
Hallo zusammen,
die Quizfrage war doch:
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:
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!”
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?
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.
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] );
}
}
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?
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.
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! 😃
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
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;
}
}
}
@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.
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
@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.