利用RegSvr32来注册.NET COM组件
2015-07-07 14:14
323 查看
背景
前一段时间由于业务关系,须要在一个比较旧的系统编写一个补丁。原系统使用VB编程,但如果要使用VB来实现这个补丁的内容,对于我这个并不怎么接触VB的人来说太头痛了。由于平时使用的是C#来开发,于是便想到能否用编写.NET COM组件的方式来让VB调用。想到这两三下便写了个.NET COM测试组件,用VB测试调用测试OK。接下来就是进行后续的开发,可等到开发完成后到了补丁打包环节却傻眼了。原来的补丁打包工具在诞生时还不知道.NET为何物,所以根本没有使用RegAsm来注册.NET COM组件的功能。现在更改打补丁工具那是不现实的,可要使得VB调用.NET
COM又必须使用RegAsm注册,这下怎么办呢?
解决方式
原打包工具是支持使用RegSvr32来注册Com组件的,忽然想到能否使用RegSvr32来注册.NET COM组件呢?印象中regsvr32在注册DLL的时候会有个CallBack函数的,于是赶紧Google找找相关资料最终解决了这个问题。主要原理是写一个代理的dll,在这个DLL的注册响应函数DllRegisterServer里调用RegAsm来注册.NET COM,同理在DllUnregisterServer里反注册。
代理DLL代码
stdafx.h
Register.cpp
前一段时间由于业务关系,须要在一个比较旧的系统编写一个补丁。原系统使用VB编程,但如果要使用VB来实现这个补丁的内容,对于我这个并不怎么接触VB的人来说太头痛了。由于平时使用的是C#来开发,于是便想到能否用编写.NET COM组件的方式来让VB调用。想到这两三下便写了个.NET COM测试组件,用VB测试调用测试OK。接下来就是进行后续的开发,可等到开发完成后到了补丁打包环节却傻眼了。原来的补丁打包工具在诞生时还不知道.NET为何物,所以根本没有使用RegAsm来注册.NET COM组件的功能。现在更改打补丁工具那是不现实的,可要使得VB调用.NET
COM又必须使用RegAsm注册,这下怎么办呢?
解决方式
原打包工具是支持使用RegSvr32来注册Com组件的,忽然想到能否使用RegSvr32来注册.NET COM组件呢?印象中regsvr32在注册DLL的时候会有个CallBack函数的,于是赶紧Google找找相关资料最终解决了这个问题。主要原理是写一个代理的dll,在这个DLL的注册响应函数DllRegisterServer里调用RegAsm来注册.NET COM,同理在DllUnregisterServer里反注册。
代理DLL代码
stdafx.h
#pragma once #include <windows.h> #include <tchar.h>
Register.cpp
/*---------------------------------------------- 此组件主要解决C#编写的COM组件无法用RegSvr32注册的问题 原理是增加一个代理DLL,在代理DLL注册时,响应DllRegisterServer注册函数, 在响应函数中使用RegAsm来注册.Net Com组件,反注册同理。 ----------------------------------------------*/ #include "stdafx.h" #define MAX_PATH 260 //全局变量,存放注册代理dll路劲 TCHAR g_FilePath[MAX_PATH]; BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { //记录代理DLL的路径,主要是为了方便后面获取代理DLL所在目录 GetModuleFileName(hModule, g_FilePath, 255); switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; } //注册响应函数 extern "C" _declspec(dllexport) long DllRegisterServer(void) { return Register(TRUE); } //反注册响应函数 extern "C" _declspec(dllexport) long DllUnregisterServer(void) { return Register(FALSE); } //注册组件 //install : TRUE for install, FALSE for unstall BOOL Register(BOOL install){ TCHAR cmd[MAX_PATH]; PROCESS_INFORMATION processInfo; STARTUPINFO stInfo; //获取注册命令 GetCmdLine(cmd, install); ZeroMemory( &processInfo, sizeof(processInfo) ); ZeroMemory( &stInfo, sizeof(stInfo) ); stInfo.cb = sizeof(stInfo); BOOL ret; //创建注册进程 ret = CreateProcess(NULL,cmd,NULL,NULL,FALSE,CREATE_NO_WINDOW,NULL,NULL,&stInfo,&processInfo); if(ret==TRUE){ CloseHandle(processInfo.hProcess); CloseHandle(processInfo.hThread); return TRUE; }else{ //DWORD error = GetLastError(); return FALSE; } return FALSE; } //获取注册命令,加/s开关可以免除确认步骤。 //注册: RegAsm.exe /s Test.dll //反注册:RegAsm.exe /s /u Test.dll void GetCmdLine(LPTSTR cmd, BOOL install){ TCHAR regAsmPath[MAX_PATH]; TCHAR regDllPath[MAX_PATH]; TCHAR temp[10]; regAsmPath[0] = '\0'; regDllPath[0] = '\0'; temp[0] = '\0'; GetRegAsmPath(regAsmPath); //获取RegAsm.exe程序绝对路径 GetRegDllPath(regDllPath); //获取需要注册的.NET COM组件绝对路径 if(install){ lstrcpy(temp, _T(" /s ")); }else{ lstrcpy(temp, _T(" /s /u ")); } cmd[0] = '\0'; lstrcat(cmd, regAsmPath); lstrcat(cmd, temp); lstrcat(cmd, regDllPath); } //获取需要注册 .Net Com 组件路径,此处写死为Test.dll,与代理dll在同一个目录 //后期可以改成读取ini配置文件 void GetRegDllPath(LPTSTR path){ int count = 0; for(int i=0; i < MAX_PATH; i++){ if(g_FilePath[i] == _T('\\')){ count = i + 2; } } TCHAR temp[MAX_PATH]; lstrcpyn(temp, g_FilePath, count); //代理DLL所在目录 lstrcat (path, _T("\"")); lstrcat (path, temp); lstrcat (path, _T("Test.dll\"")); } //获取 .NET COM 注册程序 RegAsm.exe 的路径 //方法:读取[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\InstallRoot]的值, //然后拼接上"v2.0.50727\RegAsm.exe" void GetRegAsmPath(LPTSTR path){ HKEY hKey; DWORD dwBufLen = MAX_PATH; LONG lRet; lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,_T("SOFTWARE\\Microsoft\\.NETFramework"),0, KEY_READ, &hKey); lRet = RegQueryValueEx(hKey, _T("InstallRoot"), NULL, NULL, (LPBYTE)path, &dwBufLen); RegCloseKey(hKey); lstrcat(path, _T("v2.0.50727\\RegAsm.exe")); }
相关文章推荐
- android开发的一些建议
- LeetCode Pascal's Triangle
- Git Pull Failed: CONFLICT (content): Merge conflict in camus-aggregator/camus-admin-web/src/main/web
- Android 修改keystore文件密码、alias名称
- centos普通用户设置sudo权限
- 判断2个正整数是否互质
- android 实现全屏代码
- JBossClassLoadingUseCases(jboss 类型加载使用案例)
- 【NodeJS】---增加jsonp接口
- apktool 反编译 Input file was not found or was not readable.问题解决方案
- Tomcat7 catalina.out 日志分割
- 【Scala】使用Option、Some、None,避免使用null
- 使用MegaCli和Smartctl获取普通磁盘
- 排序之冒泡排序、插入排序及希尔排序
- android studio开发apk
- Windows操作系统下jdk安装图文教程
- FFmpeg + Opencv 解码和显示
- c++ primer读书笔记-第九章 顺序容器
- 【C语言】求旋转数组的最小数字,输入一个递增排序的数组的一个旋转,输出其最小元素
- 【c++】函数模版