com-com入门2

上一篇文章简单演示了COM组件的编写,注册及调用,本篇实现COM的自注册和反注册

1. 实现COM组件的自注册和反注册

实现COM组件的自注册和反注册,本质上就是写注册表与删注册表。需要在DLL中引出两个函数:DllRegisterServer和DllUnregisterServer,让这两个函数实现注册表操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
LPCTSTR RegTable[][3] =
{
{L"CLSID\\{586CDC7B-09F1-4f44-A110-F0E604AED81E}", 0, L"BeginningCOM"},
{L"CLSID\\{586CDC7B-09F1-4f44-A110-F0E604AED81E}\\InprocServer32", 0, (LPCTSTR)-1},
{L"CLSID\\{586CDC7B-09F1-4f44-A110-F0E604AED81E}\\InprocServer32", L"ThreadingModel", L"Both"}
};

STDAPI DllUnregisterServer()
{
HRESULT hr = S_OK;

int regCount = sizeof(RegTable) / sizeof(*RegTable);

for(int i = regCount - 1; i >= 0; i--)
{
LSTATUS error = RegDeleteKey(HKEY_CLASSES_ROOT, RegTable[i][0]);

if(error != ERROR_SUCCESS)
{
hr = S_FALSE;
}
}

return hr;
}

STDAPI DllRegisterServer(void)
{
HRESULT hr = S_OK;
TCHAR szFileName[MAX_PATH];

ZeroMemory(&szFileName, MAX_PATH * sizeof(TCHAR));

GetModuleFileName(g_hModule, szFileName, MAX_PATH);

int regCount = sizeof(RegTable) / sizeof(*RegTable);

for(int i = 0; i < regCount; i++)
{
if(RegTable[i][2] == (LPCTSTR)-1)
{
RegTable[i][2] = szFileName;
}

HKEY hKey;
LSTATUS error = ::RegCreateKey(HKEY_CLASSES_ROOT, RegTable[i][0], &hKey);

if(error == ERROR_SUCCESS)
{
error = RegSetValueEx(hKey, RegTable[i][1], 0, REG_SZ, (const BYTE*)RegTable[i][2], (lstrlen(RegTable[i][2]) + 1) * sizeof(TCHAR));
RegCloseKey(hKey);
}

if(error != ERROR_SUCCESS)
{
DllUnregisterServer();
}
}

return hr;
}

现将需要修改的注册表内容放到一个二维数组中,第一维内容分别是注册表键,项,值。-1为占位符,标识该位置放置COM组件的路径,在写注册表之前将其替换。
删注册表时,应该先删子键,否则删除会失败。
同时需要在BeginningCOM.def中导出这两个函数:

1
2
3
4
5
LIBRARY    "BeginningCOM"
EXPORTS
DllGetClassObject private
DllRegisterServer private
DllUnregisterServer private

这样就可以用regsvr32.exe注册和反注册COM组件。