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

Adobe Reader ActiveX ohne Interop-Verweis versionsunabhängig in Windows.Forms hosten
Rainbird
myCSharp.de - Experte

Avatar #avatar-2834.jpg


Dabei seit:
Beiträge: 3951
Herkunft: Mauer

Themenstarter:

Adobe Reader ActiveX ohne Interop-Verweis versionsunabhängig in Windows.Forms hosten

beantworten | zitieren | melden

Beschreibung:

Dieses kleine Beispielprojekt zeigt, wie man - mit wenigen Zeilen Code - das ActiveX-Steuerelement des Adobe Readers (früher Acrobat Reader) verwenden kann, ohne einen COM-Verweis ins eigene Projekt einzufügen.

Außerdem funktioniert das mit Verschiedenen Versionen des Adobe Readers! Es spielt keine Rolle, ob man Version 7,8 oder 9 installiert hat.

Dies ist möglich, da die CLSID der verschiedenen Versionen des ActiveX-Steuerelements trotzdem immer die Selbe ist. Mit der abstrakten Basisklasse System.Windows.Forms.AxHost kann man sehr leicht Wrapper für ActiveX-Steuerelemente schreiben. Man muss nur die CLSID kennen (Wenn man nur die ProgId weiss, kann man in der Registry unter HKEY_CLASSES_ROOT danach suchen und kommt so auch an die CLSID).

Das Beispiel umfasst ein C#-Projekt mit einem Windows.Forms-Formular und einem einfachen Adobe Reader-Wrapper, der Anzeigen, Laden und Drucken kann.

Achtung! Das Beispiel funktioniert nur mit der 32-Bit Version des Readers. Die 64-Bit Version hat eine andere CLSID. Da ich leider kein 64-Bit System am laufen habe, konnte ich auch die entsprechende CLSID für die 64-Bit Reader-Version nicht ermitteln. Wenn jemand so freundlich ist, die 64-Bit CLSID zu posten, kann ich das noch mit Fallunterscheidung einbauen.

Schlagwörter: Acrobat, PDF, Adobe Reader, ActiveX, versionsunabhängig, AxHost
Attachments
private Nachricht | Beiträge des Benutzers
flippy08
myCSharp.de - Member



Dabei seit:
Beiträge: 26

beantworten | zitieren | melden

Ist es damit auch möglich das Aussehen zu bestimmen ?
So war es zB. mit dem "Normalen" ActivX möglich:


this.AxAcroPDF1.setLayoutMode("SinglePage");
this.AxAcroPDF1.setPageMode("none");
this.AxAcroPDF1.setShowToolbar(false);
private Nachricht | Beiträge des Benutzers
Rainbird
myCSharp.de - Experte

Avatar #avatar-2834.jpg


Dabei seit:
Beiträge: 3951
Herkunft: Mauer

Themenstarter:

Aussehen

beantworten | zitieren | melden

Ja, das geht ohne weiteres. Es ist ja immer noch das Selbe ActiveX-Steuerelement, nur eben über späte Bindung angesprochen. Du musst einfach Wrapper-Methoden hinzufügen (so wie LoadFile und Print). Der Zugriff auf die Original-Methoden erfolgt mittels Reflection.
private Nachricht | Beiträge des Benutzers
freako32
myCSharp.de - Member



Dabei seit:
Beiträge: 26

beantworten | zitieren | melden

hey rainbird,

danke für das tolle snippet!
ich habe einen 64bit pc zu hause, sag mir wie man die clsid herausfindet, dann geb ich die dir.
habe das bisher versucht und schon mehrere unterschiedliche clsids gefunden, aber keine hat funktioniert.
private Nachricht | Beiträge des Benutzers
Rainbird
myCSharp.de - Experte

Avatar #avatar-2834.jpg


Dabei seit:
Beiträge: 3951
Herkunft: Mauer

Themenstarter:

Clsid

beantworten | zitieren | melden

Hallo freako32,

Du solltest die CLSID finden, wenn Du in der Registry unter HKEY_CLASSES_ROOT nach "AcroPDF" suchst.
private Nachricht | Beiträge des Benutzers
Taladan
myCSharp.de - Member

Avatar #avatar-2980.jpg


Dabei seit:
Beiträge: 583
Herkunft: Osnabrück

beantworten | zitieren | melden

Hallo Rainbird,

ich deinen o.g. Code in einem WPF Control verpacken. Also erst ein WPF UserControl mit einem WindowsFormHost und darein dann das AdobeReaderControl.

Doch wenn ich dann this.GetOcx(); ausführen lasse, dann wird kein Object zurück geliefert. Eine Idee warum?
Gruß dat Tala
private Nachricht | Beiträge des Benutzers
Rainbird
myCSharp.de - Experte

Avatar #avatar-2834.jpg


Dabei seit:
Beiträge: 3951
Herkunft: Mauer

Themenstarter:

Wpf

beantworten | zitieren | melden

Hallo Taladan,

sorry, hab mit WPF sogut wie keine Erfahrung.
private Nachricht | Beiträge des Benutzers
tommaso
myCSharp.de - Member



Dabei seit:
Beiträge: 2

64bit

beantworten | zitieren | melden

Hallo zusammen

Habe den Code unter Windows 7 64bit ausprobiert und habe das Projekt auch mit der "64bit CLSID" aus der Registry nicht zu Laufen gebracht. Der Grund ist vermutlich, dass Acrobat Reader selbst keine 64bit-Version ist, sondern immer unter 32bit zu laufen scheint. Dementsprechend funktioniert mit der von Rainbird angegebenen CSLID alles bestens, wenn man explizit ein 32bit-Projekt (x86) erstellt.

Allerdings ist mir noch nicht klar, was das Erstellen eines eigenen AxHosts mit Reflection denn bringen soll. Der COM-Wrapper von Visual Studio macht ja auch nicht viel anderes, oder? Vielleicht kann Rainbird mir hier auf die Sprünge helfen?

Besten Dank,
Thomas
private Nachricht | Beiträge des Benutzers
Rainbird
myCSharp.de - Experte

Avatar #avatar-2834.jpg


Dabei seit:
Beiträge: 3951
Herkunft: Mauer

Themenstarter:

Verschiedene Reader Versionen

beantworten | zitieren | melden

Hallo tommaso,

der von VS erzeugte Wrapper läuft nicht mit verschiedenen Reader-Versionen. Ein für Adobe Reader 9 erstellter Wrapper, verweigert z.B. auf einem Kundenrechner den Dienst, auf dem nur die Version 7 installiert ist. Das ist bei meiner Methode nicht der Fall. Egal welche Reader-Version (ab 6.0 aufwärts sollte es laufen), das AxHost + Reflection Gespann arbeitet immer ordentlich.
private Nachricht | Beiträge des Benutzers
tommaso
myCSharp.de - Member



Dabei seit:
Beiträge: 2

beantworten | zitieren | melden

Danke für die Info, Rainbird. Weisst Du, weshalb das so ist? Ich dachte, der COM-Wrapper von Visual Studio referenziert auch nur eine CSLID?
private Nachricht | Beiträge des Benutzers
Rainbird
myCSharp.de - Experte

Avatar #avatar-2834.jpg


Dabei seit:
Beiträge: 3951
Herkunft: Mauer

Themenstarter:

Änderungen

beantworten | zitieren | melden

Das ist durch Unterschiede in den Schnittstellen der verschiedenen Versionen bedingt. Wenn z.B. bei einer neuen Version eine Methode plötzlich einen optionalen Parameter mehr hat, ist die Schnittstelle nicht mehr 100% kompatibel.

Mit einem spät gebundenen Aufruf klappt es aber trotzdem, vorausgesetzt man gibt nur die Parameter an, die in der ältesten zu unterstützenden Version vorhanden sind.

Natürlich können auch neue Methoden dazukommen, oder neue Enums usw.

Um genau zu untersuchen, müsste man den von AxImp.exe erzeugten Wrapper-Code analysieren. Durch anhängen von /Source an AxImp generiert das Tool nicht nur die Wrapper-Assembly, sondern spuckt auch den C#-Code dazu aus. Windows Forms ActiveX Control Importer-Tool (Aximp.exe)

Durch Anpassen des Wrapper-Codes kann man vielleicht auch die nötige Kompatibilität herstellen. Das wäre einen Versuch wert.
private Nachricht | Beiträge des Benutzers
pollito
myCSharp.de - Member

Avatar #avatar-3521.gif


Dabei seit:
Beiträge: 185

beantworten | zitieren | melden

Hallo!

Ich bin neu hier. Deswegen stelle ich mich zunächst vor: Ich programmiere seit vielen Jahren in C/C++ und Team Developer von der Fa. Unify (früher Gupta, dann Centure und heute Unify).

Seit wenigen Wochen bin ich dabei, mich in C# und das .NET-Framework einzuarbeiten. Am Anfang war das nicht gerade leicht für diesen alten C/C++-Programmierer, sich einige Sachen abzugewöhnen und andere zu erlernen. Nun bin ich ziemlich begeistert von den vielen Möglichkeiten der Sprache und des Frameworks und die Informationsgewinnung im Internet ist bärig.

Und genau durch Informationssuche bin ich auf diese Seite gestoßen. Respekt! Eine hervorragende Seite, die mir bereits geholfen hat. Ich wollte selbsterstellte PDF-Dateien in einer eigenen Form darstellen und bin in diesem Thread gelandet. Wunderbar und vielen Dank an Rainbird.

Nun zwei kurze Fragen:

1) Wo erhalte ich Information über die zur Verfügung stehenden Methoden und 2) ist die Benutzung dieses Controls kostenfrei oder muss man bei Adobe irgendetwas Lizenzieren? Ich war nämlich stundenlang auf der Adobe-Seite und habe mir das SDK angeschaut, irgendwann habe ich aber nicht mehr gewusst, was ich wirklich davon brauche und was das kostet.

Es wäre schön, wenn jemand mir diese Fragen beantworten könnte.

Vielen Dank im voraus!
René
private Nachricht | Beiträge des Benutzers
Rainbird
myCSharp.de - Experte

Avatar #avatar-2834.jpg


Dabei seit:
Beiträge: 3951
Herkunft: Mauer

Themenstarter:

beantworten | zitieren | melden

Hallo pollito,

das Control wird automatisch mit dem kostenfreien Adobe Reader installiert. Wenn immer PDF-Dateien innerhalb des Internet Explorers angezeigt werden, kommt dabei dieses ActiveX-Control zum Einsatz. Der Adobe Reader - und damit auch dessen ActiveX-Control - kann gebührenfrei genutzt werden. Details dazu kannst Du dem Lizenzvertrag des Adobe Readers entnehmen.

Kostenpflichtig ist Adobe Acrobat. Mit Acrobat kann man PDFs erstellen. Der Adobe Reader kann nur PDFs anzeigen. Wenn Du PDFs mit C# erstellen willst, gibt es eine kostenfreie Alternative zu Adobe Acrobat: iTextSharp

Du kannst ein neues Visual Studio Projekt erstellen, den COM-Verweis für das ActiveX-Control einfügen und Dir die Methoden ganz normal im Visual Studio Objektbrowser ansehen.

Ansonsten gibt es das Adobe Reader Developer Center: http://www.adobe.com/devnet/reader/

Danke für die Blumen.
private Nachricht | Beiträge des Benutzers
pollito
myCSharp.de - Member

Avatar #avatar-3521.gif


Dabei seit:
Beiträge: 185

beantworten | zitieren | melden

Hallo Rainbird,

zunächst vielen Dank für deine ausführliche Antwort.
Zitat von Rainbird
(...) Der Adobe Reader - und damit auch dessen ActiveX-Control - kann gebührenfrei genutzt werden. Details dazu kannst Du dem Lizenzvertrag des Adobe Readers entnehmen.

Danke nochmals. Mit AcroPDF erreiche fast alles, was ich brauche. Allerdings bietet dieses Control keine Möglichkeit, einen "Silent-Print" mit Angabe des Zieldruckers zu machen. Sehr schade.
Zitat von Rainbird
Wenn Du PDFs mit C# erstellen willst, gibt es eine kostenfreie Alternative zu Adobe Acrobat: iTextSharp

Ich erstelle zurzeit die PDFs über einen Umweg. Ich habe eine Anwendung, die fertige PCL-Dokumente liefert und daraus erstelle ich mit der Hilfe von VeryPDF die PDFs. Aber der von dir empfohlene Link bringt mich auf andere Ideen und ich werde sicher darauf zurück kommen.
Zitat von Rainbird
Du kannst ein neues Visual Studio Projekt erstellen, den COM-Verweis für das ActiveX-Control einfügen und Dir die Methoden ganz normal im Visual Studio Objektbrowser ansehen.

Ansonsten gibt es das Adobe Reader Developer Center: http://www.adobe.com/devnet/reader/

Ich habe mir die Methoden so angeschaut und festgestellt, dass diese in der Doku unter http://livedocs.adobe.com/acrobat_sdk/9.1/Acrobat9_1_HTMLHelp (nach "AxAcroPDFLib.AxAcroPDF" suchen) beschrieben sind.

Ist AcroPDF das einzige Bestandteil dieses SDK, welches man kostenlos nutzen darf?

Gibt es überhaupt eine Möglichkeit, die PDF-Datei zu laden und sie auf einem vorgegebenen Drucker (nicht Standarddrucker) direkt zu drucken, ohne dass der Anwender den Drucker über das Druckerdialogfeld auswählt?

Wenn das ginge, wäre AcroPDF für mich die ideale Methode.
Zitat von Rainbird
Danke für die Blumen.

Nein, ich danke dir. Die hast du dir mehr als verdient.
René
private Nachricht | Beiträge des Benutzers
jaensen
myCSharp.de - Experte

Avatar #avatar-2657.png


Dabei seit:
Beiträge: 2885
Herkunft: München

beantworten | zitieren | melden

Hallo zusammen,

mit den aktuellen Versionen des Adobe Readers gibt es eine AccessViolationException wenn man innerhalb des Controls die Tab-Taste drückt und so wie es aussieht möchte Adboe das Problem auch nicht beheben.

Habe hier einen kleinen Workaround aus dem Adobe Support-Forum (AccessViolationException fatal error, Acrobat 9, AxAcroPDFLib, .NET, Win7) eingebaut:


/// <summary>
/// .NET Wrapper für Adobe Reader ActiveX-Steuerelement
/// </summary>
public class AdobeReaderControl : AxHost {

    protected override void WndProc(ref Message m) {
        if (m.Msg == 0x1450) // Bug wenn man im reader TAB drückt (AccessViolationException) http://forums.adobe.com/thread/530591
            return;
        base.WndProc(ref m);
    }

    /// <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>
    /// Lädt eine PDF-Datei.
    /// </summary>
    /// <param name="path">Pfad</param>
    public void LoadFile(string path) {
        // LoadFile-Methode auf dem Adobe Reader aufrufen
        this.GetOcx().GetType().InvokeMember("LoadFile", BindingFlags.InvokeMethod | BindingFlags.OptionalParamBinding, null, this.GetOcx(), new object[1] { path });
    }

    /// <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
nextX
myCSharp.de - Member



Dabei seit:
Beiträge: 6

beantworten | zitieren | melden

Hallo allerseits,

ich schaffe es nicht, das Beispielprojekt zum laufen zu bringen! :-(

Die im Programm angegebene CLSID finde ich bei mir in der Registry. Allerdings habe ich keinen Acrobat 9, sondern die aktuelle Version "Adobe Reader X" Version 10.1.2.

Beim öffnen des Beispielprojektes in VS2010professional wird es erst mal konvertiert. Dabei gab es lt. Log keine Fehler oder Warungen.

Trotzdem kann ich AdobeReaderControl.cs nicht öffnen. Beim Versuch erhalte ich die Meldung "Der Designer kann keine Instanz des Typs System.Windows.Forms.AxHost erstellen, da dieser als abstrakt deklariert ist."

Starte ich das Programm trotzdem, so erhalte ich den Fehler "Klasse nicht registriert".

Für mich sieht es so aus, als wenn da ein Verweis fehlt.
Aber was muss da ggf. noch hinzugefügt werden?

Ich bin da etwas ratlos....

Caio,
N.
private Nachricht | Beiträge des Benutzers
nextX
myCSharp.de - Member



Dabei seit:
Beiträge: 6

beantworten | zitieren | melden

Ich bin der Lösung näher gekommen:

Mir ist eingefallen, daß ich ja auf einem Windows 7 64-Bit-System entwickle. So startet der Compiler offensichtlich in der Standardeinstellung "Any CPU" offensichtlich eine 64-Bit-Version meines Programmes. Die hat wieder anscheinend ein Problem mit 32-Bit-Komponenten.

Nachdem ich nun in den Eigenschaften des Projektes auf Zielplattform "x86" geschaltet habe, funktioniert alles plötzlich einwandfrei!

Nun muss ich aber irgendwie eine Lösung für dieses Mischmasch finden, denn ich kann nicht verhindern, daß mein Programm auf 64-bit-Systemen läuft, wo irgendwann später auch mal ein 64-Bit-Adobe läuft. Das wird mit Sicherheit auch wieder nicht zusammen spielen...

Aber dieses Problem haben ja sicher auch viele andere Entwickler. Also hoffe ich mal, daß da noch eine Lösung zu auftaucht.

Ciao,
N.
private Nachricht | Beiträge des Benutzers
megamacy
myCSharp.de - Member



Dabei seit:
Beiträge: 94
Herkunft: Aachen

beantworten | zitieren | melden

Ein altes Thema dass ich ausgrabe, aber dennoch brauche ich mal einen Tipp zu den Wrappern.

Ich benutze z.B. SetShowToolbar als Befehl an das ontrol, aber wenn ich es aufrufe, habe ich trpotzdem die Steuerungsleiste da von wo aus der benutzer kopien speichern und drucken kann.

Wie kann ich das ausblenden / abschalten?

Gleiches gilt für das Kontextmenü. Das sollte auch zu verhindern seinooder der inhalt anzupassen.
Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von megamacy am .
Attachments
private Nachricht | Beiträge des Benutzers
d.jonas
myCSharp.de - Member



Dabei seit:
Beiträge: 20
Herkunft: Bayern

beantworten | zitieren | melden

Auch wenn dieser Thread schon sehr alt ist..
Wenn es hierführ mittlerweile eine Lösung gibt, ich wäre auch daran interessiert!

Danke!
private Nachricht | Beiträge des Benutzers
mobobo
myCSharp.de - Member



Dabei seit:
Beiträge: 3
Herkunft: Eichsfeld

beantworten | zitieren | melden

Also auch wenn der Beitrag schon alt ist - gibt es denn da inzwischen andere Lösungen?
Ich bekomme diese Beispiel auch nicht zum laufen.

Kann man sich denn den vom Wrapper erzeugten Code irgendwo ansehen, um ihn sich eventuell zunutze zu machen?
private Nachricht | Beiträge des Benutzers