Domanda

La versione breveHo un componente aggiuntivo di Word in VB.net e VSTO che espone un oggetto compatibile COM tramite Word.COMAddins.Object, in modo che la funzionalità del componente aggiuntivo possa essere chiamata Esterna a Word, senza che gli accessi a Word stesso siano tra processi.

La tecnica funzionava in VB6, ma con VB.net funziona ancora, ma è molto più lenta dello stesso codice eseguito direttamente dal componente aggiuntivo tramite un riquadro attività, come se le chiamate fossero tutte incrociate quando non dovrebbero esserlo.X

La versione lungaQuesto componente aggiuntivo esegue essenzialmente tonnellate di elaborazione su documenti Word.Il componente aggiuntivo può essere eseguito in due modi.

  1. da Word, utilizzando un riquadro attività
  2. Esternamente, tramite un set di classi esposte a COM (perché devo fornire l'accesso alla funzionalità alle app client VB6.

MA ecco il problema.Chiunque abbia mai eseguito l'automazione di Word sa che il codice che viene eseguito INPROC in modo perfettamente accettabile con Word (in questo caso l'istanza dell'ADDIN caricato da Word stesso), generalmente verrà eseguito in modo inaccettabilmente lento fuori dal processo (o processo incrociato).

Questa app non è diversa.

Secoli fa, ho utilizzato un pratico trucco per aggirare questo problema.

  1. Crea un componente aggiuntivo di Word come al solito
  2. Esporre un oggetto tramite la proprietà word.comddin.Object che consentirà al codice esterno accedere al tuo componente aggiuntivo.
  3. Nel tuo progetto esterno, invece di manipolare direttamente Word, usa la raccolta Application.comAddins, trova il tuo componente aggiuntivo, recupera la proprietà COMADDIN.Object esposta da esso e quindi chiama un metodo su quell'oggetto che svolge il lavoro.

Naturalmente, la chiamata al tuo oggetto COMAddin.Object sarà comunque cross-process, MA, una volta che l'esecuzione è nel componente aggiuntivo IN PROCESS con Word, il tuo componente aggiuntivo ora può eseguire tutte le manipolazioni degli oggetti Word che desidera ed è veloce perché " a quel punto ci sono tutte le chiamate in corso.

Funzionava ai tempi di VB6 COM.

Ma ho messo insieme questo componente aggiuntivo VB.net vsto ed espongo il mio oggetto aggiuntivo tramite la funzione RequestComAddInAutomationService dell'oggetto Connect di VSTO

Posso effettuare chiamate al mio componente aggiuntivo esternamente e funzionano tutte esattamente come mi aspetterei, tranne che sono tutte +lente+, proprio come le chiamate a Word vengono ancora eseguite tra processi anche se il codice effettua quelle chiamate a Word fa parte della DLL del componente aggiuntivo caricata durante il processo da Word!

E lento con un fattore di circa 10 a 1;ciò che richiede 3 secondi per l'esecuzione quando viene eseguito direttamente dal componente aggiuntivo tramite il riquadro attività, richiede circa 30 secondi per l'esecuzione quando viene chiamato da codice esterno tramite l'oggetto COMADDIN.object.

Immagino che sto riscontrando una sorta di problema con .net APPDOMAINS o qualcosa del genere e cosa +realmente+ costituisce chiamate incrociate in .net, ma finora non ho trovato nulla che possa anche solo suggerire questo genere di cose.

Il mio prossimo passo, salvo qualche intuizione mistica, sarà quello di codificare una riproduzione, il che potrebbe diventare complicato a causa dell'elevato numero di elementi in gioco.

qualche idea?

È stato utile?

Soluzione 2

Sfortunatamente, la tecnica Event Hook menzionata da Thorben non funzionerebbe per la mia situazione particolare.

Quindi chiudo questa domanda con la soluzione alternativa che ho menzionato nei commenti e la ripeterò qui...

Beh, non è una soluzione perfetta, ma ho trovato +a+ soluzione.Coinvolgeva un timer, quindi è decisamente non ottimale Essenzialmente, quando il componente aggiuntivo viene caricato da Word (ovvero durante l'evento STARTUP), inizializza un timer (un timer WINFORMS, non un timer di threading) e imposta il suo intervallo su 500.Quando il codice esterno si connette al componente aggiuntivo tramite la proprietà COMADDIN.OBject ed effettua una chiamata al componente aggiuntivo, imposta un flag di variabile, che viene interrogato dal timer.Quando il timer lo vede impostato, reimposta il flag ed esegue l'azione.

Non è la soluzione pulita che avrei preferito, ma è abbastanza facile da implementare, moderatamente facile da capire a posteriori ed evita sicuramente il rallentamento delle chiamate COM xprocess in Word.

Altri suggerimenti

Ho fatto le stesse osservazioni con il mio componente aggiuntivo VSTO Word.Quello che vorrei aggiungere qui:Quando aggiungi la procedura come gestore di clic a un pulsante:

`this.testButton.Click += new Office._CommandBarButtonEvents_ClickEventHandler(YourProcedure);´

e implementare la tua costosa procedura in "YourProcedure", puoi chiamare il thread dell'interfaccia utente di Word utilizzando

this.testButton.Execute();

Anche questa non è una soluzione elegante, ma forse utile se ti capita di avere dei pulsanti pronti in una CommandBar.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top