//
// Category.cpp -
// 组件类演示程序
//
// 不编译为 UNICODE.
#include <stdlib.h>
#include <iostream.h>
#include <assert.h>
#include <comcat.h>
/////////////////////////////////////////////////
//
// 函数声明
//
// 工作函数
// 列出已注册的组件类别
BOOL ListCategories() ;
// 注册样本组件类别
BOOL RegisterCategory() ;
// 卸载样本组件类别
void UnregisterCategory() ;
// 将组件添加到样本组件类别中
void AddComponent() ;
// 从样本组件类别中移除组件
void RemoveComponent() ;
// 列出样本类别成员的所有组件
void ListCategoryMembers() ;
// 帮助函数
// 打印HRESULT所代表的COM/OLE错误信息
void ErrorMessage(const char* str, HRESULT hr) ;
// 从注册表获取和显示一个CLSID的友好名称。
// Get friendly name for a CLSID from the Registry and display.
void OutputFriendlyName(const CLSID& clsid) ;
/////////////////////////////////////////////////
//
// 全局数据和常量
//
// 全局接口指针
ICatInformation* g_pICatInformation = NULL ;
ICatRegister* g_pICatRegister = NULL ;
// 数组类别ID
// {f2484d60-e8d0-11cf-a6bb-0080c7b2d682}
static GUID CATID_SampleCategories[1] =
{0xf2484d60, 0xe8d0, 0x11cf,
{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}} ;
// 类别信息结构,用于注册类别
CATEGORYINFO g_SampleCategoryInfo =
{
{0xf2484d60, 0xe8d0, 0x11cf,
{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}}, // CATID catid
LOCALE_SYSTEM_DEFAULT, // LCID lcid
L"This is the sample category" // OLECHAR szDescription[128]
} ;
// 将组件类添加到上面定义的样本类别
// {0c092c20-882c-11cf-a6bb-0080c7b2d682}
extern "C" const CLSID CLSID_Component1 =
{0x0c092c20, 0x882c, 0x11cf,
{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}} ;
/////////////////////////////////////////////////
//
// main
//
int main()
{
// 初始化 COM 库
// OleInitialize 会调用 CoInitialize
OleInitialize(NULL) ;
// 创建标准COM类管理器
// 取代上一篇中的CallCreateInstance
// CLSID_StdComponentCategoriesMgr:待创建组件的CLSID
// NULL:指向IUnknown接口的指针,用于聚合组件,此处不需要聚合组件
// CLSCTX_ALL:运行可执行代码的上下文
// CLSCTX_ALL = CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLE
// | CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER
// = 客户希望在同一进程中运行组件 | 客户希望创建进程中处理器
// | 客户希望创建一个在同一机器上的另外一个进程中运行的组件
// | 客户希望创建一个在远程机器上运行的组件
// IID_ICatInformation:创建的Com对象的接口标识符
// (void**)&g_pICatInformation):用来接收指向Com对象接口地址的指针变量
HRESULT hr = ::CoCreateInstance(CLSID_StdComponentCategoriesMgr,
NULL,
CLSCTX_ALL,
IID_ICatInformation,
(void**)&g_pICatInformation) ;
if (FAILED(hr))
{
ErrorMessage("main: Could not create component category manager.", hr) ;
goto Uninitialize ;
}
// 列出类别
if (!ListCategories())
{
goto Release ;
}
// 得到类别的注册接口
hr = g_pICatInformation->QueryInterface(IID_ICatRegister,
(void**)&g_pICatRegister) ;
if (FAILED(hr))
{
ErrorMessage("Attempt to query for ICatRegister failed.", hr) ;
goto Release ;
}
//
// 注册样本组件类别
//
cout << "--------Register---------------" << endl ;
if (!RegisterCategory())
{
goto Release ;
}
// 再次列出类别,以显示新注册的类别
ListCategories() ;
// 添加组件到样本类别
cout << "--------Add Component----------" << endl ;
AddComponent() ;
// 列出样本类别的所有组件
cout << "--------List Category----------" << endl ;
ListCategoryMembers();
// 从样本类别中移除组件
cout << "--------Remove Component-------" << endl ;
RemoveComponent();
// 列出样本类别的所有组件
// 应该为空
cout << "--------List Category----------" << endl ;
ListCategoryMembers() ;
// 注销样品组件类别
cout << "--------Unregister-------------" << endl ;
UnregisterCategory() ;
// 列出要显示组件类别的类别们
// 已经被移除
ListCategories() ;
Release:
// 释放接口指针
if (g_pICatInformation != NULL)
{
g_pICatInformation->Release() ;
}
if (g_pICatRegister != NULL)
{
g_pICatRegister->Release() ;
}
Uninitialize:
// 注销 COM 库
OleUninitialize() ;
return 0 ;
}
/////////////////////////////////////////////////
//
// 工作函数
//
//
// 列出已注册的组件类别
//
BOOL ListCategories()
{
BOOL bReturn = TRUE ;
// 得到类别的 enumerator
IEnumCATEGORYINFO* pIEnumCATEGORYINFO = NULL ;
HRESULT hr = g_pICatInformation->EnumCategories(::GetUserDefaultLCID(),
&pIEnumCATEGORYINFO) ;
if (FAILED(hr))
{
ErrorMessage("ListCategories: ICatInformation::EnumCategories failed.", hr) ;
return FALSE ;
}
// 循环准备
char szDescription[128] ;
CATEGORYINFO CategoryInfo ;
// 枚举类别
while ((hr = pIEnumCATEGORYINFO->Next(1, &CategoryInfo, NULL)) == S_OK)
{
// 将 wchar_t 转换为 char.
::wcstombs(szDescription, CategoryInfo.szDescription,
sizeof(szDescription)) ;
// 输出描述信息
cout << szDescription << "\r\n" ;
}
if (FAILED(hr))
{
ErrorMessage("ListCategories: IEnumCATEGORYINFO::Next failed.", hr) ;
bReturn = FALSE ;
}
// 释放接口
if (pIEnumCATEGORYINFO != NULL)
{
pIEnumCATEGORYINFO->Release() ;
}
return bReturn ;
}
//
// 注册组件类别
//
BOOL RegisterCategory()
{
HRESULT hr = g_pICatRegister->RegisterCategories(1, &g_SampleCategoryInfo) ;
if (FAILED(hr))
{
ErrorMessage("RegisterCategory: Registering the component category failed.",
hr) ;
return FALSE ;
}
return TRUE ;
}
//
// 销毁组件类别
//
void UnregisterCategory()
{
HRESULT hr = g_pICatRegister->UnRegisterCategories(1, CATID_SampleCategories) ;
if (FAILED(hr))
{
ErrorMessage("UnregisterCategory: Unregistering component category failed.",
hr) ;
}
}
//
// 为组件类别添加组件
//
void AddComponent()
{
HRESULT hr = g_pICatRegister->RegisterClassImplCategories(CLSID_Component1,
1,
CATID_SampleCategories) ;
if (FAILED(hr))
{
ErrorMessage("AddComponent: Adding component to category failed.", hr) ;
}
}
//
// 从组件类别中移除组件
//
void RemoveComponent()
{
HRESULT hr =
g_pICatRegister->UnRegisterClassImplCategories(CLSID_Component1,
1,
CATID_SampleCategories) ;
if (FAILED(hr))
{
ErrorMessage("RemoveComponent: Removing component to category failed.",
hr) ;
}
}
//
// 列出属于特定类别成员的所有组件
//
void ListCategoryMembers()
{
// 获得类别枚举器
IEnumCLSID* pIEnumCLSID = NULL;
HRESULT hr
= g_pICatInformation->EnumClassesOfCategories(1,
CATID_SampleCategories,
0,
NULL,
&pIEnumCLSID) ;
if (FAILED(hr))
{
ErrorMessage("ListCategoryMembers: EnumClassesOfCategories failed.", hr) ;
}
// 循环准备
char szDescription[128] ;
CLSID clsid ;
// 枚举类别
while (TRUE)
{
// 获得下一个类别
hr = pIEnumCLSID->Next( 1, &clsid, NULL) ;
if (hr != S_OK)
{
if (FAILED(hr))
{
ErrorMessage("ListCategoryMembers: IEnumCLSID::Next failed.",
hr) ;
}
break ;
}
// 打印友好名称
OutputFriendlyName(clsid) ;
}
// 释放接口
if (pIEnumCLSID != NULL)
{
pIEnumCLSID->Release() ;
}
}
/////////////////////////////////////////////////
//
// Helper 函数
//
// 输出HRESULT所代表的COM/OLE错误信息
void ErrorMessage(const char* str, HRESULT hr)
{
void* pMsgBuf ;
//将HRESULT所代表错误信息转换为字符串
//第1个参数:标志位,决定如何说明第2个参数
//FORMAT_MESSAGE_ALLOCATE_BUFFER:分配一个足够大的缓冲区保存格式化信息
//FORMAT_MESSAGE_FROM_SYSTEM:为请求的信息搜索系统的消息资源表
//NULL:根据第1个参数而定
//hr:请求消息的标识符
//第4个参数:请求的消息的语言标识符
//(LPTSTR) &pMsgBuf:接收错误信息描述的缓冲区指针
//0:输出缓冲区的大小
//NULL:保存格式化信息中的插入值的一个数组
::FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
hr,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 默认语言
(LPTSTR) &pMsgBuf,
0,
NULL
) ;
// 显示字符串
cout << str << "\r\n" ;
cout << "Error (" << hex << hr << "): "
<< (char*)pMsgBuf << endl ;
// 释放缓冲区
LocalFree( pMsgBuf ) ;
}
//
// 从注册表获取并显示一个CLSID的友好名称
//
void OutputFriendlyName(const CLSID& clsid)
{
// 将 clsid 转换为一个字符串
wchar_t wszCLSID[80] ;
int r = ::StringFromGUID2(clsid, wszCLSID, 80) ;
assert(r != 0) ;
// 转换为单字节字符.
char szCLSID[40] ;
wcstombs(szCLSID, wszCLSID, 40) ;
// 打开注册表项
HKEY key = NULL ;
long l = ::RegOpenKeyEx(HKEY_CLASSES_ROOT,
"CLSID",
0,
KEY_ALL_ACCESS,
&key) ;
assert(l == ERROR_SUCCESS) ;
// 得到友好名称
char szFriendly[256] ;
long size = sizeof(szFriendly) ;
l = ::RegQueryValue(key,
szCLSID,
szFriendly,
&size) ;
assert(l == ERROR_SUCCESS) ;
// 输出友好名称
cout << szFriendly << endl ;
// 清空
::RegCloseKey(key) ;
}
COM---注册表
最新推荐文章于 2024-08-19 22:22:04 发布