|
Broken links? Email us! |
|
There are two interfaces to the Component Category Manager: the registration interface and the information interface. The registration interface is used by COM objects during their registration, or by setup programs to register an object as belonging to, or requiring a particular category. The information interface is then used by the application needing to use a category of objects. I wrote two classes to wrap these interfaces up.
CComCatRegister
wraps an ICatRegister
interface and provides a
thin wrapper around the standard functionality. The advantages of using the wrapper class
are that for the simplest registration requirements you can just instantiate it and call
a single function to register your object...
CComCatRegister catMgr; catMgr.RegisterClassImplCategories(myGUID, myCATID);
If you also need to register the category, the above becomes...
CComCatRegister catMgr; catMgr.RegisterCategory(myCATID, _T("This is a category")); catMgr.RegisterClassImplCategories(myGUID, myCATID);
You can also register the class as belonging to multiple categories, or register categories that the class requires, rather than implements.
That's about all there is to using the registration category manager. Compare this to
the boiler-plate code required to initialise COM, get an ICatRegister
interface, manage its lifetime, provide the locale ID for the category descriptions,
etc, etc... It's easier!
ICatInformation
.
This is used by applications that want to discover which objects belong to which
categories, which categories an object requires, which categories it implements, etc.
As with CComCatRegister
, CComCatInformation
wraps the standard
COM interface in a thin wrapper. This class adds more value that CComCatRegister
as the underlying interface is more complex. Using the IEnumXXXX
iterator
wrappers that are explained
here it neatly
wraps all of the IEnum
interfaces available from ICatInformation
and makes them easier to use.
If you wanted to display a list of objects implementing a particular category then all you need do is something like this...
CComCatInformation catMgr; CIterateGUID start = catMgr.IterateClassesOfCategory(myCATID); CIterateGUID end = CIterateGUID::End(); for (CIterateGUID ⁢ = begin; it != end; ++it) { LPOLESTR lpGUIDString; if (S_OK == StringFromIID(it, &lpGUIDString;)) { std::wcout << L" " << lpGUIDString << std::endl; CoTaskMemFree(lpGUIDString); } }
Compare this code to that found in the
IEnum
sample that doesn't use the Component Category Manager.
IEnumCATID
that is supplied
with the standard component category manager. I have version 4.71 of ComCat.dll
on my machine and calling Clone()
on an IEnumCATID
interface
pointer which was obained from a call to either EnumImplCategoriesOfClass()
or EnumReqCategoriesOfClass()
gives you a pointer which appears to be linked
to the original pointer you called Clone()
on. Calling Release()
on
either the cloned pointer or the original appears to invalidate the other... This is
certainly not the case with the other IEnum
interfaces presented by the
component category manager.
The problem can be seen with the code below (there's a complete test program available for from the download page).
IEnumCATID *pIEnumCatid = 0; hr = pICatInfo->EnumImplCategoriesOfClass(guid, &pIEnumCatid;); if (SUCCEEDED(hr)) { IEnumCATID *pIEnumCatidClone = 0; hr = pIEnumCatid->Clone(&pIEnumCatidClone;); if (SUCCEEDED(hr)) { pIEnumCatid->Release(); pIEnumCatidClone->Release(); // Doesn't matter which order these are // the second release causes an access // violation... } }
Apparantly a new version of the component category manager is available with VB6.0 the version of ComCat.dll should be 5.0. I would be intestested to know if this bug is still present in the latest version. Version 5.0 is also supposedly part of IE4sr1 but I have that installed and still have 4.71
EnumImplCategoriesOfClass()
and EnumReqCategoriesOfClass()
are probably the least used functions on the ICatInformation
interface, and
for most uses you wouldn't need to call Clone()
on an interface pointer obtained
from them. However, it causes problems with my wrapper class as the iterators are returned
by value and this causes the interface pointer to be Clone()
d in the copy
constructor of the IEnumIterator...
If the test program fails on your machine, do not use
CComCatInformation::IterateImplCategoriesOfClass()
or
CComCatInformation::IterateReqCategoriesOfClass()
.
See the article on Len's homepage for the latest updates.
Len has been programming for over 20 years, having first started with a Sinclair ZX-80. Now he's a C++ consultant, specialising in COM+ or CORBA on Windows or Unix.
Click here to visit Len Holgate's homepage.
|
|