2009-10-25 4 views
8

COM è noto per rendere possibile la compatibilità con le versioni precedenti quando si rilasciano nuovi componenti o applicazioni. Ciò è possibile perché le interfacce in COM sono stabili, cioè non cambiano.Come si evolve un'interfaccia COM?

Ho provato a trovare un riferimento o un libro che si occupi di una descrizione su come evocare un'interfaccia COM dalla versione alla versione.

Di seguito sono le mie esigenze:

Abbiamo un'applicazione che può essere guidato da OLE Automation. Le nuove versioni di questa applicazione possono essere installate in parallelo alle versioni precedenti.

I client COM di questa applicazione possono utilizzare PROGID indipendente dalla versione nel qual caso funzionano con la versione più recente dell'applicazione o PROGID dipendente dalla versione, nel qual caso funzionano con la versione specifica dell'applicazione.

Le modifiche all'automazione COM non devono interrompere nessuno dei client.

Vediamo un esempio:

#include <olectl.h> 
#include <fxbase\autoif.h> 

[ 
    uuid(A1B3A66F-806F-46a2-82D9-9C278F415148), 
    lcid(-1), 
    version(1.0) 
] 

library LIB 
{ 
     importlib("stdole2.tlb"); 

     [ 
      uuid(82CDE055-790A-4505-BF3E-3282170C8FC6), 
      helpstring("Document"), 
      oleautomation, 
      dual, 
      nonextensible 
     ] 
     interface IDocument : IDispatch 
     { 
       [id(0x00000001), propget, helpcontext(0x0012c94a)] 
       HRESULT Name([out, retval] BSTR* psName); 

       [id(0x00000001), propput, helpcontext(0x0012c94a)] 
       HRESULT Name([in] BSTR psName); 
     } 

     [ 
      uuid(919B9E6E-76C0-4c23-A188-5840E5900997), 
      helpstring("Application object."), 
      oleautomation, 
      dual, 
      nonextensible 
     ] 
     interface IApplication : IDispatch 
     { 
      [id(0x00000001), propget, helpstring("Returns the active document of the application.")] 
      HRESULT ActiveDocument([out, retval] IDocument** retval); 
     } 

     [ 
      uuid(E0AA6FCA-AEF1-460b-A1F9-26250C28594B), 
      helpstring("Application 1.0 Class"), 
      appobject 
     ] 
     coclass Application 
     { 
      [default] interface IApplication; 
           interface IDispatch; 
     } 
} 

Diciamo che voglio pubblicare la versione 2.0 di questa applicazione che si estende alcune interfacce. Qui è il mio approccio ingenuo alla versione 2.0:

#include <olectl.h> 
#include <fxbase\autoif.h> 

[ 
    uuid(3D4688A2-91F8-4cd8-989A-845810A05557), 
    lcid(-1), 
    version(2.0) 
] 

library LIB 
{ 
     importlib("stdole2.tlb"); 

     [ 
      uuid(82CDE055-790A-4505-BF3E-3282170C8FC6), 
      helpstring("Document"), 
      oleautomation, 
      dual 
     ] 
     interface IDocument10 : IDispatch 
     { 
       [id(0x00000001), propget, helpcontext(0x0012c94a)] 
       HRESULT Name([out, retval] BSTR* psName); 

       [id(0x00000001), propput, helpcontext(0x0012c94a)] 
       HRESULT Name([in] BSTR psName); 
     } 

     [ 
      uuid(AF404510-216A-407e-99F4-0636AF071B68), 
      helpstring("Document"), 
      oleautomation, 
      dual, 
      nonextensible 
     ] 
     interface IDocument : IDocument10 
     { 
       [id(0x00000001), propget, helpcontext(0x0012c94a)] 
       HRESULT Type([out, retval] BSTR* psType); 

       [id(0x00000001), propput, helpcontext(0x0012c94a)] 
       HRESULT Type([in] BSTR psType); 
     } 

     [ 
      uuid(919B9E6E-76C0-4c23-A188-5840E5900997), 
      helpstring("Application object."), 
      oleautomation, 
      dual 
     ] 
     interface IApplication10 : IDispatch 
     { 
      [id(0x00000001), propget, helpstring("Returns the active document of the application.")] 
      HRESULT ActiveDocument([out, retval] IDocument** retval); 
     } 

     [ 
      uuid(6A851C3F-21DF-4f5e-A4D6-2EF5A9D234C6), 
      helpstring("Application object."), 
      oleautomation, 
      dual, 
      nonextensible 
     ] 
     interface IApplication : IApplication10 
     { 
      [id(0x00000002), propget, helpstring("Is the application visible.")] 
      HRESULT Visible([out, retval] BOOL* retval); 
     } 

     [ 
      uuid(AA760349-1682-4ab6-BF0C-C02E620715CF), 
      helpstring("Application 2.0 Class"), 
      appobject 
     ] 
     coclass Application 
     { 
      [default] interface IApplication; 
           interface IDispatch; 
     } 
} 

E 'questo il modo corretto di fare questo?

Devo aggiungere una classe Application10 e Application20 al Registro di sistema per aggiungere una possibilità di istanziare le diverse versioni dell'applicazione per i client di script?

È corretto modificare la versione e il GUID della libreria dei tipi?

L'IDocumento nella versione 2.0 ha un nuovo IID. Posso comunque utilizzare IDocument in IApplication.ActiveDocument?

Come devo registrare la coclea o l'interfaccia nel registro di Windows nelle diverse versioni?

Si noti che non utilizzo ATL o altre librerie diverse da WIN32-API.

Se si sa dove posso trovare informazioni su questo (libri, riferimenti, ecc.), Suggerirne uno.

Apprezzerei molto il vostro aiuto.

risposta

10

Sì, è necessario modificare lo class id dell'oggetto se si desidera che più versioni coesistano. Tuttavia è possibile mantenere uno program id indipendente dalla versione come "Word.Application" o "InternetExplorer.Application" che redirects to the class id of the current version. La compatibilità con le versioni precedenti è molto difficile da mantenere. Apparentemente MSXML ha abbandonato la pratica del progID indipendente dalla versione.

Se si decide di mantenere le interfacce obsolete (consigliato), è necessario implementare entrambe le interfacce nuove e vecchie nel nuovo oggetto.

È possibile controllare le voci di registro di Microsoft Office. Mantiene abbastanza bene la retrocompatibilità.

Il nome suggerito di nuove interfacce sarebbe il nome dell'interfaccia e il numero di versione, ad esempio IHtmlDocument6.

+0

Vorrei davvero imparare dalle voci del Registro di sistema di Microsoft Office ma non ho una versione precedente. Conoscete programmi freeware da cui imparare? – frast

+0

Perché è necessario modificare il CLSID? L'implementazione implementerà ancora tutte le interfacce che ha fatto, giusto? –

+0

@frast o controlla IE. –