2009-10-25 12 views
8

System COM umożliwia kompatybilność wsteczną po zwolnieniu nowych komponentów lub aplikacji. Jest to możliwe, ponieważ interfejsy w COM są stabilne, tzn. Nie zmieniają się.Jak ewoluować interfejs COM?

Próbowałem ciężko znaleźć odniesienie lub książkę, która zajmuje się opisem, jak ewakuować interfejs COM z wersji do wersji.

Oto moje wymagania:

Mamy aplikacji, które mogą być napędzane przez OLE Automation. Nowe wersje tej aplikacji można zainstalować równolegle do starszych wersji.

Klienci COM tej aplikacji mogą korzystać z niezależnego od wersji PROGID, w którym to przypadku pracują z najnowszą wersją aplikacji lub z zależnym od wersji PROGID, w którym to przypadku pracują z określoną wersją aplikacji.

Zmiany w automatyzacji COM nie powinny powodować problemów z żadnym z klientów.

Pozwala zobaczyć przykład:

#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; 
     } 
} 

Powiedzmy chcę opublikować wersję 2.0 tej aplikacji, która rozciąga się kilka interfejsów. Oto moje naiwne podejście do wersji 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; 
     } 
} 

Czy to jest właściwy sposób na zrobienie tego?

Czy powinienem dodać klasę Application10 i Application20 do rejestru, aby dodać możliwość utworzenia różnych wersji aplikacji dla klientów skryptów?

Czy można zmienić wersję GUID biblioteki typów, podając numer i?

IDocument w wersji 2.0 ma nowe IID. Czy nadal mogę używać IDocument w pliku IApplication.ActiveDocument?

W jaki sposób należy zarejestrować coclass lub interfejs w rejestrze systemu Windows w różnych wersjach?

Należy pamiętać, że nie używam biblioteki ATL ani innych bibliotek innych niż WIN32-API.

Jeśli wiesz, gdzie mogę znaleźć informacje na ten temat (książki, referencje itp.), Zasugeruj jedną.

Byłbym wdzięczny za pomoc.

Odpowiedz

10

Tak, musisz zmienić class id swojego obiektu, jeśli chcesz, aby wiele wersji współistniało. Można jednak zachować niezależne od wersji program id, takie jak "Word.Application" lub "InternetExplorer.Application" pod adresem redirects to the class id of the current version. Kompatybilność wsteczna jest bardzo trudna do utrzymania. MSXML najwyraźniej porzucił praktykę progID niezależną od wersji.

Jeśli zdecydujesz się zachować stare interfejsy (zalecane), musisz zaimplementować nowy i stary interfejs w swoim nowym obiekcie.

Możesz chcieć sprawdzić wpisy w rejestrze Microsoft Office. Bardzo dobrze zachowuje kompatybilność wsteczną.

Sugerowana nazwa nowych interfejsów to nazwa interakcji z numerem wersji, na przykład IHtmlDocument6.

+0

Naprawdę chciałbym dowiedzieć się z wpisów rejestru Microsoft Office, ale nie mam starej wersji. Czy znasz darmowe programy do nauki? – frast

+0

Dlaczego konieczna jest zmiana identyfikatora CLSID? Wdrożenie nadal będzie implementować wszystkie interfejsy, które wykonał, prawda? –

+0

@frast lub sprawdź IE. –