Posted on 2010-12-09 09:15
Sivan 阅读(2150)
评论(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"))
代码如下:
1CString 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
16void 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}