动态加载DLL的方法与注意的问题
dll加载原理

dll加载原理DLL加载原理概述•DLL(动态链接库)是一种可执行文件格式,用于存储和共享程序代码和数据。
•DLL加载是将DLL文件加载到内存并解析其导出函数的过程。
DLL的分类•内核模式DLL:运行在操作系统内核空间中,提供给操作系统使用。
•用户模式DLL:运行在应用程序进程的用户空间中,为应用程序提供功能支持。
DLL的加载方式1.隐式加载:在应用程序启动时由操作系统自动加载所需的DLL文件。
–应用程序代码中使用函数,操作系统自动在加载应用程序的同时加载其依赖的DLL。
–应用程序代码需要将DLL的路径告知操作系统,操作系统根据路径找到DLL并加载。
2.显式加载:在应用程序运行时手动加载所需的DLL文件。
–应用程序通过调用加载函数(如LoadLibrary函数)手动加载DLL。
–调用GetProcAdress函数获取DLL中函数的入口地址,从而调用DLL中的函数。
DLL的加载过程1.读取DLL文件:–操作系统通过文件系统读取DLL文件的内容。
2.根据DLL文件的导入表(Import Table)解析DLL的依赖:–导入表记录了DLL所依赖的其他DLL,以及导出函数的名称和地址。
3.加载DLL依赖的其他DLL:–递归地加载DLL所依赖的其他DLL文件。
4.解析DLL导出函数:–根据导入表中记录的函数名称,找到导出函数的入口地址。
5.将DLL文件映射到进程空间:–将DLL文件映射到进程的虚拟内存空间中,以便能够访问DLL中的代码和数据。
6.更新进程的导入表:–更新进程的导入表,将DLL中导出函数的地址填入相应的入口地址。
DLL的卸载•当不再需要某个DLL时,可以将其从内存中卸载。
•DLL卸载的条件通常是没有其他模块依赖该DLL,或者由操作系统决定。
总结•DLL加载是将DLL文件加载到内存并解析导出函数的过程。
•DLL可以通过隐式加载或显式加载的方式加载。
•DLL的加载过程包括读取DLL文件、解析依赖、加载其他DLL、解析导出函数等步骤。
动态链接库的使用方法

动态链接库的使用方法动态链接库(Dynamic Link Library,DLL)是Windows系统中一种常见的文件类型,用于存储可被程序在运行时动态加载的函数和数据。
它可以提供代码和资源的共享,使得程序的安装包更小,节省了系统资源。
使用动态链接库有以下几个优点:1.模块化:将程序代码和资源划分为独立的模块,便于开发和维护。
2.共享性:多个程序可以共享同一个动态链接库,减少重复的代码和数据的存储。
3.动态加载:可以在程序运行时动态地加载和卸载动态链接库,提高了程序的灵活性和可扩展性。
1.创建动态链接库:使用C/C++编程语言可以创建动态链接库。
首先,在开发环境中创建新的DLL项目,并选择动态链接库的类型。
在项目中添加需要的代码和资源,并编写相应的函数和数据接口。
将这些接口封装在一个头文件中,并在源文件中实现具体的功能。
最后,编译项目生成动态链接库文件(.dll 文件)。
2.导出函数和数据:在动态链接库中,明确指定哪些函数和数据需要被其他程序调用。
在函数和数据的声明前加上__declspec(dllexport)关键字即可。
例如:```C++__declspec(dllexport) int Add(int a, int b);```3.调用动态链接库:在其他程序中调用动态链接库中的函数和数据,需要先导入相应的函数和数据。
使用C/C++编程语言可以创建一个头文件,其中包含要导入的函数和数据的声明。
例如:```C++__declspec(dllimport) int Add(int a, int b);__declspec(dllimport) extern double PI;```然后,在使用这些函数和数据的源文件中包含这个头文件即可。
4.加载和卸载动态链接库:在程序运行时,需要动态地加载动态链接库,并在使用完之后卸载。
可以使用LoadLibrary函数来加载动态链接库,使用FreeLibrary函数来卸载动态链接库。
加载DLL文件失败的解决办法

开机提示找不到 *.dll 解决小结。
最近这个问题很多,把这个也总结一下吧,欢迎大家提出其它意见供大家参考:首先查一下是哪个.dll无法加载,试着手动regsvr32 *.dll加载试试1、开始-运行,输入msconfig,在“启动”中把相关自启动的选项都去掉。
2、关闭系统还原。
(我的电脑-属性-系统还原,选择“在所有的驱动器上关闭系统还原”)3、把C:\Documents and Settings\用户名\Local Settings\Temp和C:\Documents and Settings\用户名\Local Settings\Temporary Internet Files文件夹下的所有文件都删除。
(如果看不到此文件夹,工具-文件夹选项,在“查看”中有一项是“隐藏文件和文件夹”,选择“显示所有文件和文件夹”)4、把C:\WINDOWS\Prefetch文件夹下的所有文件都删除。
5、控制面板-服务,把你认为不需要的服务都改为“手动”并停用。
6、关闭各种视觉效果(我的电脑-属性,弹出的窗口里选择“高级”标签,性能的设置,选择最佳性能,或者只保留倒数第二项、倒数第三项和在窗口和按钮上保持视觉样式。
)7、关闭远程协助(我的电脑-属性,弹出的窗口里选择“远程”标签,然后取消下面两个选项的选择。
)8、安装优化软件(二者选一即可) TuneUp Utilities 或者 Windows 优化大师或者其它的......可能是这个dll因为某些原因(最大的可能是因为它是个病毒或流氓软件的dll 文件,被杀软删除了)丢失了,但其相关的注册信息却还在,导致系统开机时还加载它,却又找不到它的文件,所以报错。
如果你点击“确定”后,系统没有什么不正常,并且可以正常运行的话,你可以用这个软件清理掉这个开机加载项,以后开机就不会出现这个信息了。
Autoruns:开机启动项管理DLL文件即动态链接库文件,是一种可执行文件,它允许程序共享执行特殊任务所必需的代码和其他资源。
WORD打开时出现加载DLL错误解决方法

WORD打开时出现加载DLL错误解决方法WORD打开时出现加载DLL错误解决方法
1、接下来看看解决办法,按组合键WIN + R或者按开始---运行,打开运行窗口,
2、在运行对话框中输入或者复制粘贴
“%USERPROFILE%\AppData\Roaming\Microsoft\T emplate s”(注意双引号就不要输入咧),输入完成后,点击确定按钮。
3、然后的打开的窗口中将“Normal.dotm”文件删除,
4、到这里已经把问题完美解决啦,其实还有一种方法捏,仍然是打开开始---运行(或者按WIN + R快捷键),输入“regedit”(双引号不要输入)打开注册表。
5、进入注册表编辑器后,分别找到(定位)“HKEY_CURRENT_USER”和“HKEY_LOCAL_MACHINE”两个选项,
6、点击左侧的小箭头展开注册表选项,分别找到
“HKEY_CURRENT_USER\Software\Microsoft\Office\14.0\W ord”和“HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\Word\A ddi ns”
7、然后分别在找到的两个选项上点击右键---删除就OK咧。
动态链接库知识点总结之三(如何以显示的方式加载DLL)

动态链接库知识点总结之三(如何以显⽰的⽅式加载DLL)总结⼀下如何显⽰加载⽅式加载DLL,⾸先,我们新建⼀个win32项⽬,选择dll,空项⽬,再添加⼀个源⽂件,⼀个模块定义⽂件(.def),具体如下图。
(详细⽅法已经在前两篇⽂章中讲述,如有不懂,打开链接查看)(1) 新建项⽬,名称为:dll,添加⼀个源⽂件(.cpp),编代码,编译⽂件。
(2) 为项⽬添加⼀个模块定义⽂件(上⼀篇⽂章中详细介绍)(先新建⼀个⽂本,再改属性名),编辑代码,如下图(3) 新建⼀个DLL测试应⽤程序(基于对话框的),项⽬名字:TestDLL,添加⼀个按钮,属性如下,先编译⼀下。
(4) 为按钮添加⼀个响应函数,编写如下代码(具体代码含义在最后介绍)(5) 把已经编译好的DLL,选择.dll⽂件将拷贝到应⽤程序⽬录下(dll放在与该测试⽂件的.exe⽂件夹下(具体做法已在前两篇介绍过),如图(7) 点击,运⾏,成功运⾏,以显⽰的⽅式加载DLL成功现在介绍下,按钮消息响应函数中的代码含义。
函数LoadLibrary()作⽤是将可执⾏模块映射到进程的地址空间,通俗点来说,就是可以⽤来加载DLL的,这个函数是显⽰加载DLL的重要函数。
参数是DLL的名称,这个函数在MSDN上有详细的解释,⼤家可以通过以下链接查看。
该函数返回的是所加载的DLL的句柄。
()有了DLL的句柄,我们需要再获得导出函数的地址即可,获得地址,⽤此函数:GetProcAddress(),参数1是:DLL句柄,参数2:⼀个指针,指向导出函数的名字。
该函数返回值如果为NULL,则获取地址失败。
成功,则返回导出函数的导出地址。
有了地址,我们如何操纵函数,我们还需要⼀个函数指针,使⽤函数指针来调⽤导出函数。
在此我们总结⼀下:动态加载DLL时,客户端程序不再需要包含引⼊库⽂件,只需要.dll⽂件即可。
静态加载和动态加载各有各的优缺点,⾸先,静态加载DLL⽐较简单,但是如果需要加载的DLL过多的话会造成启动程序过慢,所以还是选择动态加载⽐较好。
c#实现动态加载Dll

c#实现动态加载Dll原理如下:1、利用反射进行动态加载和调用.Assembly ass=Assembly.LoadFrom(DllPath); //利用dll的路径加载,同时将此程序集所依赖的程序集加载进来,需后辍名.dllAssembly.LoadFile 只加载指定文件,并不会自动加载依赖程序集.Assmbly.Load无需后辍名2、加载dll后,需要使用dll中某类.Type type=ass.GetType(“TypeName”);//用类型的命名空间和名称获得类型3、需要实例化类型,才可以使用,参数可以人为的指定,也可以无参数,静态实例可以省略Object obj = Activator.CreateInstance(type,params[]);//利用指定的参数实例话类型4、调用类型中的某个方法:需要首先得到此方法MethodInfo mi=type.GetMethod(“MehtodName”);//通过方法名称获得方法5、然后对方法进行调用,多态性利用参数进行控制mi.Invoke(obj,params[]);//根据参数直线方法,返回值就是原方法的返回值#region 声明动态载入DLL的参数object obj=null;byte[] filesByte;Assembly assembly;Type type;MethodInfo timerInitial;MethodInfo timerDispose;#endregionprivate void LoadDll()//加载DLL{try{filesByte = File.ReadAllBytes(Path.GetDirectoryName(Application.ExecutablePath) + "\\loadDll.dll");assembly = Assembly.Load(filesByte);type = assembly.GetType("test.loadDll");obj = System.Activator.CreateInstance(type);timerStart = tp.GetMethod("TimerStart");timerStop = tp.GetMethod("TimerStop");if (timerStart != null){timerStart.Invoke(obj, null);}}catch(Exception){}}以下摘自MSDNpublic class A{public virtual int method () {return 0;}}public class B{public virtual int method () {return 1;}}class Mymethodinfo{public static int Main(){Console.WriteLine ("\nReflection.MethodInfo");A MyA = new A();B MyB = new B();// Get the Type and MethodInfo.Type MyTypea = Type.GetType("A");MethodInfo Mymethodinfoa = MyTypea.GetMethod("method");Type MyTypeb = Type.GetType("B");MethodInfo Mymethodinfob = MyTypeb.GetMethod("method");// Get and display the Invoke method.Console.Write("\nFirst method - " + MyTypea.FullName +" returns " + Mymethodinfoa.Invoke(MyA, null));Console.Write("\nSecond method - " + MyTypeb.FullName + " returns " + Mymethodinfob.Invoke(MyB, null));return 0;}}。
C#实现动态加载dll的方法

C#实现动态加载dll的⽅法本⽂实例讲述了C#实现动态加载dll的⽅法。
分享给⼤家供⼤家参考。
具体实现⽅法如下:复制代码代码如下:using System;using System.Collections.Generic;using System.Text;using System.Reflection;using System.IO;namespace monAPI.DynamicLoadAssembly{public class AssemblyDynamicLoader<T>{private AppDomain appDomain;private DynamicRemoteLoadAssembly<T> remoteLoader;public T InvokeMethod(string assemblyName, string assemblyPath, string assemblyConfigFilePath, string fullClassName, string methodName, params object[] args){AppDomainSetup setup = new AppDomainSetup();setup.ApplicationName = "ApplicationLoader";setup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory + @"bin\";//setup.PrivateBinPath = bine(AppDomain.CurrentDomain.BaseDirectory, "private");setup.CachePath = setup.ApplicationBase;setup.ShadowCopyFiles = "true";if (assemblyConfigFilePath != string.Empty){setup.ConfigurationFile = AppDomain.CurrentDomain.BaseDirectory + assemblyConfigFilePath;}setup.ShadowCopyDirectories = setup.ApplicationBase;setup.LoaderOptimization = LoaderOptimization.SingleDomain;this.appDomain = AppDomain.CreateDomain("ApplicationLoaderDomain", null, setup);String name = Assembly.GetExecutingAssembly().GetName().FullName;this.remoteLoader = (DynamicRemoteLoadAssembly<T>)this.appDomain.CreateInstanceAndUnwrap(name, typeof(DynamicRemoteLoadAssembly<T>).FullName);assemblyName = AppDomain.CurrentDomain.BaseDirectory + assemblyPath + assemblyName;return this.remoteLoader.InvokeMethod(assemblyName, fullClassName, methodName, args);}/// <summary>////// </summary>public void Unload(){try{AppDomain.Unload(this.appDomain);this.appDomain = null;}catch (CannotUnloadAppDomainException ex){}}}}复制代码代码如下:using System;using System.Collections.Generic;using System.Text;using System.Reflection;using System.Globalization;namespace monAPI.DynamicLoadAssembly{public class DynamicRemoteLoadAssembly<T> : MarshalByRefObject{private Assembly assembly = null;public T InvokeMethod(string assemblyPath, string fullClassName, string methodName, params object[] args){this.assembly = null;T result = default(T);try{this.assembly = Assembly.LoadFile(assemblyPath);Type pgmType = null;if (this.assembly != null){pgmType = this.assembly.GetType(fullClassName, true, true);}else{pgmType = Type.GetType(fullClassName, true, true);}BindingFlags defaultBinding = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.InvokeMethod | BindingFlags.Static;CultureInfo cultureInfo = new CultureInfo("es-ES", false);try{MethodInfo methisInfo = assembly.GetType(fullClassName, true, true).GetMethod(methodName);if (methisInfo == null){new Exception("EMethod does not exist!");}if (methisInfo.IsStatic){if (methisInfo.GetParameters().Length == 0){if (methisInfo.ReturnType == typeof(void)){pgmType.InvokeMember(methodName, defaultBinding, null, null, null, cultureInfo);}else{result = (T)pgmType.InvokeMember(methodName, defaultBinding, null, null, null, cultureInfo);}}else{if (methisInfo.ReturnType == typeof(void)){pgmType.InvokeMember(methodName, defaultBinding, null, null, args, cultureInfo);}else{result = (T)pgmType.InvokeMember(methodName, defaultBinding, null, null, args, cultureInfo);}}}else{if (methisInfo.GetParameters().Length == 0){object pgmClass = Activator.CreateInstance(pgmType);if (methisInfo.ReturnType == typeof(void)){pgmType.InvokeMember(methodName, defaultBinding, null, pgmClass, null, cultureInfo);}else{result = (T)pgmType.InvokeMember(methodName, defaultBinding, null, pgmClass, null, cultureInfo); }}else{object pgmClass = Activator.CreateInstance(pgmType);if (methisInfo.ReturnType == typeof(void)){pgmType.InvokeMember(methodName, defaultBinding, null, pgmClass, args, cultureInfo);}else{result = (T)pgmType.InvokeMember(methodName, defaultBinding, null, pgmClass, args, cultureInfo); }}}}catch (Exception e){result = (T)pgmType.InvokeMember(methodName, defaultBinding, null, null, null, cultureInfo);}return result;}catch (Exception ee){return result;}}}}希望本⽂所述对⼤家的C#程序设计有所帮助。
C#动态载入DLL,并调用成员方法(提供非接口及接口调用两种方式)

public int Max(int a, int b) {
return a > b ? a : b; } public int Min(int a, int b) {
return a < b ? a : b; } }
}
Form 源代码
private void button1_Click(object sender, EventArgs e)
return a > b ? a : b; }
} }
Form 源码,添加 TextBox 和 Button 控件
private void button1_Click(object sender, EventArgs e)
{
try
{
Assembly ass = Assembly.LoadFrom("TestDll.dll"); Type t = ass.GetType("TestDll.TestA"); object obj = Activator.CreateInstance(t); MethodInfo method = t.GetMethod("Max"); textBox1.Text += "Max(10, 20): " + method.Invoke(obj, new object[] { 10, 20 }).ToString();
} public TestC(int a, int b) {
A = a; B = b; } public int Max() { return a > b ? a : b; } public int Min() { return a < b ? a : b; }}
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
动态加载DLL的方法与注意的问题
加载DLL的方法主要有两种:一种是隐式链接,另外一种是动态加载。
隐式链接会把DLL中所有标志为_declspec(dllexport)的函数都加载,如果有多个DLL 加载时,可能会影响到程序执行的效率。
而用动态加载DLL的方式则可以根据需要去加载用到的函数。
动态加载DLL的方法:
1.生成dll过程:把生成的.DLL文件复制到测试工程DLLTest目录下。
这里假设该.DLL 文件为add.dll,主要代码是:
Extern “C” _declspec(dllexport) int add(int x, int y)
{
return x + y;
}
2.使用1生成的dll:在DLLTest工程中添加DllTest.cpp文件.
首先使用LoadLibrary("add.dll")加载add.dll文件:
HMODULE hmod = LoadLibrary("add.dll");
然后定义一个函数指针的类型:
typedef int (*AddAddr)(int x, int y);
注意,这里的参数与返回类型务必与add.dll文件中函数add的声明一样。
接着:
AddAddr Add = (AddAddr)GetProcAddress(hmod, "add");
如果Add值为空,则获取函数的地址失败!
if(!Add)
{
printf("获取函数地址失败!");
return;
}
最后,可以测试一下:
printf("test add(): 1+2=%d", add(1,2));
运行结果一看,会出现“获取函数地址失败!”。
为什么会这样?
打开命令行,用cd命令到add.dll工程目录的debug目录下,然后使用命令:dumpbin -exports add.dll
则会看到add.dll文件中的add函数的名称为“?add@@YAHHH@Z”,而不是函数名add,这是C++编译器的命名改编机制。
修改原来的代码:
AddAddr Add = (AddAddr)GetProcAddress(hmod, "?add@@YAHHH@Z");
这时运行就成功了。
但如果按这样去动态加载DLL,那每次获取函数地址都要使用dumpbin 命令去获取,则会很麻烦。
那怎样可以直接使用add而不是?add@@YAHHH@Z这个长长的字符串呢,修改add.dll 的add函数,在函数前加上extern "C",再编译add.dll文件所在的工程,复制新生成的add.dll覆盖DLLTest工程目录下的add.dll,原来的代码获取函数地址时使用add,结果运行就成功了。
而再使用dumpbin -exports add.dll命令,显示add.dll的中的add函数的名称变成了add.。