C# 使用代码实现非托管dll、OCX动态注册

一般我们注册VB的ocx控件或者其他的dll需要手动在控制台命令中用regsvr32来注册,其实就是调用dll中的DllRegisterServer方法,用c#的DllImport也可以调用该方法,但是DllImport的路径必须是静态字段,不能动态的,我们可以使用kernel32中的两个函数来实现动态调用:LoadLibrary和GetProcAddress,调用完成之后再FreeLibrary就可以了,先上代码:

  /// 
    /// 动态加载DLL
    /// 
    public class DynamicLoadDll
    {
        /// 
        /// 根据非托管库的句柄,函数名称和指定委托类型,返回委托
        /// 
        /// 
        /// 
        /// 
        /// 
        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);//将非托管函数指针转换为委托。
        }
        /// 
        /// 根据dll的路径,dll中的方法名,动态调用非托管dll的方法
        /// 
        /// dll的路径
        /// 要调用的dll的方法名称
        /// 要将对应非托管dll中的方法名映射为C#的签名一致的委托类型
        /// 执行过程中的错误信息
        /// 执行方法的参数
        /// 
        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
    {
        /// 
        /// API LoadLibrary
        /// 
        [DllImport("kernel32")]
        public static extern int LoadLibrary(string funcName);

        /// 
        /// API GetProcAddress
        /// 
        [DllImport("kernel32")]
        public static extern int GetProcAddress(int handle, string funcName);

        /// 
        /// API FreeLibrary
        /// 
        [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

你可能感兴趣的:(C#)