none
Problem mit VSTO-Plugin bei mehreren geöffneten Word-AddIns RRS feed

  • Frage

  • Hallo zusammen,

    ich habe ein ernsthaftes Problem mit einem Word-AddIn welches mit VSTO erstellt wurde. Das AddIn funktioniert wunderbar wenn ich ein Word-Dokument geöffnet habe. Öffne ich nun ein weiteres Word-Dokument (von einer Word-Instanz möchte ich nicht sprechen, da kein neuer Prozess im TaskManager dazu kommt) und möchte dort ebenfalls das AddIn laden, funktioniert das nicht.
    Erst wenn ich im neugeöffneten Word-Dokument das (nicht angezeigte) AddIn schließe, kann ich es danach laden. Dabei wird dann im ersten Word-Dokument das AddIn geschlossen.

    Daraus schließe ich messerscharf ;), dass es nur eine Instanz dieses AddIns gibt. Deshalb ist es logischerweise erst dann möglich das AddIn in einem zweiten Dokument zu öffnen wenn es im ersten geschlossen ist.

    Hier noch ein paar Infos zu meinem AddIn:

    Das AddIn besteht aus einer Ribbonbar. Innerhalb dieser Ribbonbar befinden sich zwei Buttons. Über einen Button wird das eigentliche AddIn geladen, über einen anderen geschlossen. Das "eigentliche" AddIn besteht aus einem UserControl welches geladen wird. So sieht (gekürzt) der Code meiner Ribbonbar aus.

    public
     class
     Ribbon : OfficeRibbon
    {
        CustomTaskPane TaskPane = null
    ;
        Frontend frontend = null
    ;
    
        public
     Ribbon()
        {
            InitializeComponent();
        }
    
        private
     void
     btnShow_Click(object
     sender, RibbonControlEventArgs e)
        {
            if
     (frontend != null
    )
                return
    ;
    
            frontend = new
     Frontend();
    
            TaskPane = Globals.ThisAddIn.CustomTaskPanes.Add(frontend, "Blubb :)"
    );
            TaskPane.DockPosition = Microsoft.Office.Core.MsoCTPDockPosition.msoCTPDockPositionRight;
            TaskPane.Visible = true
    ;
            TaskPane.Width = 280;
        }
    
        private
     void
     btnHide_Click(object
     sender, RibbonControlEventArgs e)
        {
            frontend = null
    ;
    
            if
     (TaskPane != null
    )
                Globals.ThisAddIn.CustomTaskPanes.Remove(TaskPane);
        }
    }
    


    Wenn jemand grobe Fehler sieht bin ich auch dankbar wenn mir diese mitgeteilt werden.

    Vielen Dank und viele Grüße!!!
    Montag, 26. Oktober 2009 13:11

Antworten

  • Hallo Ryder101,

    das Problem ist nicht das Add-In, sondern der benutzerdefinierte Aufgabenbereich. Die Ursache liegt darin, dass Word eine SDI-Anwendung ist und jedes Dokument sein eigenes Anwendungsfenster hat. Die benutzerdefinierten Aufgabenbereiche verhalten sich entsprechend und so hat auch jedes Dokument seinen eigenen Aufgabenbereich (anders als bei Excel zum Beispiel, wo ein Aufgabenbereich anwendungsweit gültig ist).

    Du musst das UserControl also jedem einzelnen Dokument hinzufügen. Je nachdem, wann das UserControl angezeigt werden soll, musst du also das ensprechende Ereignis behandeln, welches beim Öffnen, Erstellen oder Aktivieren eines (neuen) Dokuments ausgelöst wird. Innerhalb der Methode für den Ereigishandler fügst du das UserControl dem Dokument dann mit dem gleichen Code hinzu, den du bereits gepostet hast. In diesem Fall hast du dann in der Anzahl soviele Aufgabenbereiche wie Dokumente. Wenn dies nicht gewünscht ist, musst du dafür sorgen, dass der Aufgabenbereich aus einem gerade nicht aktuellen Dokument enfernt und dafür in dem aktuellen Dokument angezeigt wird.

    Nähere Infos zur Vorgehensweise findest du unter:
    http://msdn.microsoft.com/de-de/library/aa942864.aspx
    http://msdn.microsoft.com/de-de/library/bb608620.aspx

    Der zweite Link enthält auch Beispielcode und eine Auflistung der Ereignisse, die für das Vorgehen behandelt werden können.

    Viele Grüße
    Jan
    • Als Antwort vorgeschlagen Jan Tittel Samstag, 31. Oktober 2009 11:47
    • Als Antwort markiert Ryder101 Montag, 2. November 2009 12:15
    Montag, 26. Oktober 2009 15:53

Alle Antworten

  • Hallo Ryder101,

    das Problem ist nicht das Add-In, sondern der benutzerdefinierte Aufgabenbereich. Die Ursache liegt darin, dass Word eine SDI-Anwendung ist und jedes Dokument sein eigenes Anwendungsfenster hat. Die benutzerdefinierten Aufgabenbereiche verhalten sich entsprechend und so hat auch jedes Dokument seinen eigenen Aufgabenbereich (anders als bei Excel zum Beispiel, wo ein Aufgabenbereich anwendungsweit gültig ist).

    Du musst das UserControl also jedem einzelnen Dokument hinzufügen. Je nachdem, wann das UserControl angezeigt werden soll, musst du also das ensprechende Ereignis behandeln, welches beim Öffnen, Erstellen oder Aktivieren eines (neuen) Dokuments ausgelöst wird. Innerhalb der Methode für den Ereigishandler fügst du das UserControl dem Dokument dann mit dem gleichen Code hinzu, den du bereits gepostet hast. In diesem Fall hast du dann in der Anzahl soviele Aufgabenbereiche wie Dokumente. Wenn dies nicht gewünscht ist, musst du dafür sorgen, dass der Aufgabenbereich aus einem gerade nicht aktuellen Dokument enfernt und dafür in dem aktuellen Dokument angezeigt wird.

    Nähere Infos zur Vorgehensweise findest du unter:
    http://msdn.microsoft.com/de-de/library/aa942864.aspx
    http://msdn.microsoft.com/de-de/library/bb608620.aspx

    Der zweite Link enthält auch Beispielcode und eine Auflistung der Ereignisse, die für das Vorgehen behandelt werden können.

    Viele Grüße
    Jan
    • Als Antwort vorgeschlagen Jan Tittel Samstag, 31. Oktober 2009 11:47
    • Als Antwort markiert Ryder101 Montag, 2. November 2009 12:15
    Montag, 26. Oktober 2009 15:53
  • Hallo Jan!

    Vielen Dank für deine Antwort. Ich werde leider erst am Mittwoch dazu kommen, mich mit dem Problem zu befassen. Aber da werde ich mich auf jeden Fall nochmal melden.

    Danke schön!
    Montag, 26. Oktober 2009 15:59
  • Hallo Jan,

    jetzt bleibt mir doch noch eine halbe Stunde, weshalb ich mir das nochmals kurz angeschaut habe. Das Problem habe ich verstanden, das prinzipielle Vorgehen eigentlich auch. Mein Hauptproblem ist gerade, dass ich nicht weiß in welchen Eventhandler ich den entsprechenden Code eintragen muss.
    Ich habe dazu auch kein Codebeispiel gefunden?! Wenn es an meinem persönlichen Unvermögen liegt bitte ich das zu entschuldigen :-/ Aber kannst du mir sagen wo die Events (DocumentOpen, NewDocument, etc...) gefeuert werden, bzw. wo ich diese Events abfangen kann?

    Vielen Dank!
    Montag, 26. Oktober 2009 16:27
  • Hallo Ryder101,

    der Beispielcode unter dem zweiten Link zeigt bereits die Vorgehensweise für Excel. Für Word sieht es ganz ähnlich aus, nur dass die Events anders heißen. Frage ist hier, was du behandeln möchtest. In jedem Fall gehört der Code in die ThisAddIn-Klasse. Auf die Events kann über das Application-Objekt zugegriffen werden. Also zum Beispiel Application.DocumentOpen, Application.WindowActivate oder Application.WindowDeactivate.

    Für das Event Application.DocumentOpen sieht ein Codeausschnitt folgendermaßen aus:

     

    private void ThisAddIn_Startup(object sender, System.EventArgs e) 
    
    {
    
    Application.DocumentOpen +=new Microsoft.Office.Interop.Word.ApplicationEvents4_DocumentOpenEventHandler(Application_DocumentOpen); 
    
    }
    
    void Application_DocumentOpen(Word.Document Doc) 
    
    {
    
    //Laden des benutzerdefinierten Aufgabenbereichs
    
    }

     


    Viele Grüße
    Jan

    Montag, 26. Oktober 2009 18:57
  • Hi Jan!

    Das mit den Events habe ich verstanden, was übrigens sehr interessant ist. Es gibt eine Menge Events, die ich nicht kannte. Das kann später sehr nützlich sein.

    Aber das eigentliche Problem konnte ich leider noch nicht lösen. So bin ich vorgegangen:

    Folgender Code wird bei WindowActivate aufgerufen:
    Frontend frontend = new Frontend();
    TaskPane = Globals.ThisAddIn.CustomTaskPanes.Add(frontend, "Blubb :)");
    TaskPane.DockPosition = Microsoft.Office.Core.MsoCTPDockPosition.msoCTPDockPositionRight;
    TaskPane.Width = 280;


    Im Eventhandler des Buttons zum Anzeigen des Frontends, der sich in der Ribbonbar befindet, ist folgender Code:

    Globals.ThisAddIn.CustomTaskPanes[0].Visible = true;
    So ist es im Beispielcode für Excel auch gelöst. Allerdings funktioniert das nicht. Das UserControl existiert immer noch nur in einer Instanz, auf die ich über zwei unterschiedliche Word-Fenster Zugriff habe.

    Was muss ich da noch abändern?

    Vielen Dank!
    Mittwoch, 28. Oktober 2009 10:11
  • Hi Ryder101,

    du erstellt in den Eventhandlern neue Instanzen der Aufgabenbereiche, die nichts mit der ersten Instanz zu tun haben. Du musst hier ebenfalls die Eigenschaft Visible auf true setzen.

    Dadurch gerät natürlich dein Ribbon durcheinander, welches die Ansicht steuert. Idealerweise sollte dies wie unter

    http://msdn.microsoft.com/de-de/library/bb608590.aspx

    beschrieben gehandhabt werden.

    Viele Grüße
    Jan
    Mittwoch, 28. Oktober 2009 10:27
  • Hi Jan,

    ich bin kurz davor zu verzweifeln... :( Ich habe es in Word genau so umgesetzt wie es dort beschrieben ist. Die Erklärungen sind ja sehr genau und hilfreich. Allerdings funktionierte es nicht. Dann habe ich es in Excel implementiert, genau wie im Beispiel. Dort funktioniert es wunderbar. Anschließend habe ich nochmal versucht es in Word umzusetzen. Doch auch das ist gescheitert...

    Kann es sein dass das Beispiel nicht für Word 2007 funktioniert? Auch wenn es dort steht? Eine weitere Person hat gerade ebenfalls nochmal darüber geschaut, und keine Fehler in der Word-Implementierung gefunden. Also sind eigentlich Fehler meinerseits ausgeschlossen =/

    Viele Grüße
    Mittwoch, 28. Oktober 2009 12:24
  • Hi Jan,

    ich habe jetzt vermutlich den Knackpunkt gefunden, warum es nicht funktioniert. Trotzdem bin ich von der Lösung meilenweit entfernt.

    Ich rufe sowohl im ThisAddIn_Startup-Handler des Excel-AddIns als auch des Word-AddIns eine MessageBox auf. Die MessageBox von Excel erscheint jedes mal wenn ich eine neues Excel-Fenster öffne. Bei Word erscheint sie nur beim ersten Fenster.

    Das bedeutet dass der ThisAddIn_Startup-Handler bei Word nur einmal aufgerufen wird und bei Excel pro Instanz einmal. Dann ist klar dass mir Word keine neue Instanz des AddIns anlegt.

    Aber wie umgehe ich das Problem? Ist dann nicht die verlinkte Anleitung falsch? Die Anleitung funktioniert doch nur wenn pro geöffnetes Fenster der ThisAddIn_Startup-Handler aufgerufen wird, oder?

    Viele Grüße
    Mittwoch, 28. Oktober 2009 12:37
  • Hi Jan,

    ich habe jetzt vermutlich den Knackpunkt gefunden, warum es nicht funktioniert. Trotzdem bin ich von der Lösung meilenweit entfernt.

    Ich rufe sowohl im ThisAddIn_Startup-Handler des Excel-AddIns als auch des Word-AddIns eine MessageBox auf. Die MessageBox von Excel erscheint jedes mal wenn ich eine neues Excel-Fenster öffne. Bei Word erscheint sie nur beim ersten Fenster.

    Das bedeutet dass der ThisAddIn_Startup-Handler bei Word nur einmal aufgerufen wird und bei Excel pro Instanz einmal. Dann ist klar dass mir Word keine neue Instanz des AddIns anlegt.

    Aber wie umgehe ich das Problem? Ist dann nicht die verlinkte Anleitung falsch? Die Anleitung funktioniert doch nur wenn pro geöffnetes Fenster der ThisAddIn_Startup-Handler aufgerufen wird, oder?

    Viele Grüße


    Hallo Ryder

    Vielleicht habe ich es in den vielen Nachrichten verpasst, aber...

    WIE werden diese mehreren Instanzen von Excel gestartet? Klickt der Benutzer auf ein Icon? Doppelklickt er auf eine Arbeitsmappe? Wird Excel von einer anderen Anwendung aus ferngesteuert?

    Im Gegensatz zu Word, wenn der Benutzer nochmals auf ein Excel 2007 Icon klickt, wird eine neue Instanz gestartet; Word benutzt die Laufende. Wenn Du statt auf das Icon anzuklicken eine neue Arbeitsmappe erstellen würdest (Ctrl+N, beispielsweise), würdest Du in der gleichen Instanz bleiben.

    Da ich kein Excel-Spezialist bin, weiss ich nicht, ob dieses Verhalten geändert werden kann (durch eine Registry-Eintrag, vielleicht, oder eine Ergänzung der Befehlszeile, die hinter dem Icon-Shortcut liegt). Ah, hier finde ich eine mögliche Antwort (Englisch!). Siehe die Antwort von pgc01 vom 15. Sept 2007, um 03:26 PM. Sie wird auf vom Fragesteller als Lösung bestätigt.


    Cindy Meister, VSTO/Word MVP
    Donnerstag, 29. Oktober 2009 08:28
  • Hallo Ryder101,

    sorry für die verspätete Antwort! Vielleicht habe ich mich zuvor etwas missverständlich ausgedrückt. Das Add-In selbst (ebenso wie eine Erweiterung der Multifunktionsleiste) wird in Word nur einmal geladen und gilt anwendungsweit. Das unterschiedliche Verhalten der Fenster von Word und Excel (SDI/MDI) betrifft hier nur die benutzerdefinierten Aufgabenbereiche. Insofern solltest du schon auf dem richtigen Weg sein. Lediglich muss der Aufgabenbereich in Word abhängig vom Dokument geladen werden - beispielsweise im Event DocumentOpen, wie oben beschrieben. Innerhalb von ThisAddIn_Startup wird der Aufgabenbereich nur für das erste Dokument geladen, da ja auch das AddIn selbst nur einmal geladen wird...

    Viele Grüße
    Jan
    Donnerstag, 29. Oktober 2009 10:29
  • Hi!

    Ich habe es jetzt wie folgt gelöst:

    string windowTitle = "Titel der Anwendung - " + Globals.ThisAddIn.Application.ActiveDocument.Name;
    foreach (CustomTaskPane ctpTemp in Globals.ThisAddIn.CustomTaskPanes)
    {
        if (ctpTemp.Title == windowTitle)
        {
            return;
        }
    }

    _Frontend = new Frontend();
    _TaskPane = Globals.ThisAddIn.CustomTaskPanes.Add(_Frontend, windowTitle);
    _TaskPane.Visible = true;
    _TaskPane.Width   = 280;

    So hat jedes AddIn einen anderen Namen und die AddIns können geladen werden.

    Vielen Dank für eure Hilfe!!!
    Viele Grüße :)
    Montag, 2. November 2009 09:33
  • Hi Cindy,

    das Problem ist aber nicht das Verhalten von Excel sondern eher das Verhalten von Word. Ich habe es jetzt anders gelöst.

    Trotzdem vielen Dank dass du dich meines Problems angenommen hast :)

    Viele Grüße
    Montag, 2. November 2009 09:34