Posted on 2010-12-09 09:15
Sivan 閱讀(2176)
評論(0) 編輯 收藏 引用 所屬分類:
VC/MFC
1.概述
經常會遇到這樣的情況:每次重裝了系統,因為注冊表丟失,一些軟件(在非系統分區的軟件目錄)需要重新注冊目錄中的DLL(DLL是組件的需要注冊)或OCX才能成功運行。通常我們會手動在“運行”中輸入“regsvr32 /s dll/ocx路徑”進行手段注冊,或者寫一個如下面形式的批處理文件
regsvr32 /s Plugin\CBDict08\CBDataSet.dll
regsvr32 /s Plugin\CBNetDict08\CBNetDataSet.dll
regsvr32 /s plugin\CBGoogleDataSet\CBGoogleDataSet.dll
regsvr32 /s plugin\CBNetDicDict\CBNetDicDataSet.dll
regsvr32 /s cache.dll
批處理文件固然簡單高效,但是將每個目錄中的DLL和OCX都提取出來,然后寫批處理文件也是挺繁瑣的一件事情,能不能只用一個小程序將目錄中的DLL與OCX都自動注冊呢?本文解決這個小問題。
2.解決方法
自動注冊程序目錄下的DLL和OCX,需要經過以下幾個步驟。
獲得本程序所在目錄路徑→搜尋本目錄下的DLL和OCX文件→裝載DLL或OCX→調用DLL注冊進入點函數DllRegisterServer/或反注冊函數DllUnregisterServer→卸載DLL或OCX。這個過程主要用到了四個函數。
(1)LoadLibary
HMODULE LoadLibrary(LPCTSTR lpFileName);
LoadLibrary載入指定可執行模塊,并將它映射到當前進程地址空間。載入后,可以訪問庫內的資源。
(2)FreeLibrary
BOOL FreeLibrary(HMODULE hModule);
FreeLibrary用于釋放LoadLibary函數載入的動態鏈接庫。
(3)DllRegisterServer
STDAPI DllRegisterServer(void);
通知一個進程內服務創建它的注冊入口點。
(4)DllUnregisterServer
STDAPI DllUnregisterServer(void);
通知進程內服務移除通過DllRegisterServer創建的入口點。
注意:直接調用DLL內函數需要使用GetProcAddress,而GetProcAddress是Windows API,在Windows32平臺導出函數名是ANSI字符的,它的第二個參數為LPCSTR(const char*)類型,在Unicode編譯模式下,如果第二個參數有L或_T修飾,可能編譯不通。可以寫成如下形式
(RegSvrFun)GetProcAddress(hModule, (LPCSTR)("DllUnregisterServer"))

代碼如下:
1
CString CRegisterDlg::GetExePath()
2

{
3
TCHAR szPath[MAX_PATH];
4
::GetModuleFileName(NULL, szPath, MAX_PATH);
5
TCHAR* pChr = _tcsrchr(szPath, _T('\\'));
6
CString strVal;
7
if (pChr != NULL)
8
{
9
*pChr = _T('\0');
10
lstrcpy(strVal.GetBuffer(MAX_PATH), szPath);
11
strVal.ReleaseBuffer(MAX_PATH);
12
}
13
return strVal;
14
}
15
16
void CRegisterDlg::OnBnClickedBtnReg()
17

{
18
// TODO: 在此添加控件通知處理程序代碼
19
CString strDir;
20
strDir = GetExePath();
21
if (strDir.IsEmpty())
22
{
23
MessageBox(_T("尋找程序運行目錄錯誤!"), _T("錯誤"), MB_OK | MB_ICONSTOP);
24
return;
25
}
26
27
BeginWaitCursor();
28
29
CStringArray saAllFile,saFile;
30
CFileFind filefind;
31
CString strFind;
32
BOOL bFind = FALSE;
33
34
saAllFile.RemoveAll();
35
strFind.Format(_T("%s\\*.*"), strDir);
36
bFind = filefind.FindFile(strFind);
37
while (bFind)
38
{
39
bFind = filefind.FindNextFile();
40
if (!filefind.IsDirectory() && !filefind.IsDots())
41
{
42
CString strPath;
43
strPath = filefind.GetFilePath();
44
TRACE(_T("%s\n"),strPath);
45
saAllFile.Add(strPath.MakeLower());
46
}
47
}
48
saAllFile.FreeExtra();
49
saFile.RemoveAll();
50
for (int i=0; i!=saAllFile.GetCount(); ++i)
51
{
52
CString strTemp = saAllFile.GetAt(i).Right(4);
53
if (strTemp == _T(".dll") || strTemp == _T(".ocx"))
54
{
55
saFile.Add(saAllFile.GetAt(i));
56
}
57
}
58
saFile.FreeExtra();
59
if (saFile.GetCount() == 0)
60
{
61
MessageBox(_T("目錄中沒有需要注冊的文件!"), _T("提示"), MB_OK | MB_ICONINFORMATION);
62
return;
63
}
64
CStringArray saOK,saFail;
65
saOK.RemoveAll();
66
saFail.RemoveAll();
67
for (int i=0; i!=saFile.GetCount(); ++i)
68
{
69
CString strPath;
70
strPath = saFile.GetAt(i);
71
HMODULE hModule = LoadLibrary(strPath);
72
if (hModule == NULL)
73
{
74
saFail.Add(strPath);
75
return;
76
}
77
RegSvrFun DllRegisterServer = (RegSvrFun)GetProcAddress(hModule, (LPCSTR)("DllRegisterServer"));
78
if (DllRegisterServer != NULL)
79
{
80
HRESULT ret = DllRegisterServer();
81
if (ret == S_OK)
82
{
83
saOK.Add(strPath);
84
}
85
else
86
{
87
saFail.Add(strPath);
88
}
89
}
90
else
91
{
92
saFail.Add(strPath);
93
}
94
FreeLibrary(hModule);
95
}
96
CString strMsg = _T("注冊成功的文件有:\n");
97
for (int i=0; i!=saOK.GetCount(); ++i)
98
{
99
CString strTemp = saOK.GetAt(i);
100
strTemp += _T("\n");
101
strMsg += strTemp;
102
}
103
strMsg += _T("\n注冊失敗的文件有:\n");
104
for (int i=0; i!=saFail.GetCount(); ++i)
105
{
106
CString strTemp = saFail.GetAt(i);
107
strTemp += _T("\n");
108
strMsg += strTemp;
109
}
110
EndWaitCursor();
111
MessageBox(strMsg,_T("提示"),MB_OK | MB_ICONINFORMATION);
112
}