一般我们注册VB的ocx控件或者其他的dll需要手动在控制台命令中用regsvr32来注册,其实就是调用dll中的DllRegisterServer方法,用c#的DllImport也可以调用该方法,但是DllImport的路径必须是静态字段,不能动态的,我们可以使用kernel32中的两个函数来实现动态调用:LoadLibrary和GetProcAddress,调用完成之后再FreeLibrary就可以了,先上代码:
/// <summary>
/// 动态加载DLL
/// </summary>
public class DynamicLoadDll
{
/// <summary>
/// 根据非托管库的句柄,函数名称和指定委托类型,返回委托
/// </summary>
/// <param name="dllModule"></param>
/// <param name="functionName"></param>
/// <param name="t"></param>
/// <returns></returns>
private static Delegate GetFunctionAddress(int dllModule, string functionName, Type t)
{
int address = Kernel32Helper.GetProcAddress(dllModule, functionName); //得到地址
if (address == 0)
return null;
else
return Marshal.GetDelegateForFunctionPointer(new IntPtr(address), t);//将非托管函数指针转换为委托。
}
/// <summary>
/// 根据dll的路径,dll中的方法名,动态调用非托管dll的方法
/// </summary>
/// <param name="dllPath">dll的路径</param>
/// <param name="functionName">要调用的dll的方法名称</param>
/// <param name="delegateType">要将对应非托管dll中的方法名映射为C#的签名一致的委托类型</param>
/// <param name="msg">执行过程中的错误信息</param>
/// <param name="par">执行方法的参数</param>
/// <returns></returns>
public static object DynamicInvoke(string dllPath, string functionName,Type delegateType,out string msg,params object[] par)
{
msg = "";
int address = 0;
try
{
address = Kernel32Helper.LoadLibrary(dllPath);
if (address == 0)
{
msg = "加载dll失败,dll路径:" + dllPath;
return null;
}
Delegate d1 = GetFunctionAddress(address, functionName, delegateType);
if (d1 == null)
{
msg = "获取函数名称失败,函数名称:" + functionName;
return null;
}
object result= d1.DynamicInvoke(par);
Kernel32Helper.FreeLibrary(address);
return result;
}
catch (Exception e)
{
if (address != 0)
{
Kernel32Helper.FreeLibrary(address);
}
msg = e.Message;
return null;
}
}
}
public class Kernel32Helper
{
/// <summary>
/// API LoadLibrary
/// </summary>
[DllImport("kernel32")]
public static extern int LoadLibrary(string funcName);
/// <summary>
/// API GetProcAddress
/// </summary>
[DllImport("kernel32")]
public static extern int GetProcAddress(int handle, string funcName);
/// <summary>
/// API FreeLibrary
/// </summary>
[DllImport("kernel32")]
public static extern int FreeLibrary(int handle);
}
使用:
class Program
{
public delegate int DllRegisterHandler();
public delegate int DllUnregisterHandler();
static void Main(string[] args)
{
string msg = "";
string dllFunction = "DllRegisterServer";
string[] dllPathList = System.IO.Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory,"*.ocx", System.IO.SearchOption.TopDirectoryOnly);
if (dllPathList != null && dllPathList.Length > 0)
{
foreach (var dllPath in dllPathList)
{
object o = DynamicLoadDll.DynamicInvoke(dllPath, dllFunction, typeof(DllRegisterHandler), out msg);
if (o != null && (int)o >= 0)
{
Console.WriteLine(dllPath + "注册成功!");
}
else
{
Console.WriteLine(dllPath + "注册失败" + msg);
}
}
}
Console.Read();
}
}
上面的代码就是获取程序目录下的ocx文件,然后注册这些获取到的ocx文件,
需要注意的是:编译的时候不能选择Any CPU,要选择x86,不然LoadLibrary会不成功!!这是用经验走过的坑
github下载地址:https://github.com/lishuangquan1987/OneKeyRegister