前言
概念
-
动态链接库: 它是一个win32(32位操作系统环境)的概念,以dll为后缀的文件,可以有VC++,C++Builder,Delphi等生成。动态链接库不能调用.net程序集。
-
程序集: 它是一个.net 的概念,可以是dll也可以是exe文件,程序集里面包含了:程序集清单(manifest),类型元数据,Microsoft中间语言(MSIL)代码以及其他资源。
程序集清单包含有:程序集名称,版本信息,区域性信息,强名称信息,程序集文件列表,类型引用信息,引用和依赖程序集信息。
在默认情况下,创建一个程序集,是该应用程序专有的,如果要共享该程序集,必须要加强名称表明该程序集是安全的然后再全局应用程序域缓存(GAC)发布。程序集具有一个语言无关性,也就是说可以用任何一种.net 的语言来开发程序集,然后可以被.net的其他语言使用。例如,可以在 Microsoft Visual C# 中开发程序集,然后在 Microsoft Visual Basic .NET 项目中使用该程序集。
.net程序集可以调用动态链接库。
首先明白一个前提:C#是托管型代码。C++是非托管型代码。
-
托管型代码的对象在托管堆上分配内存,创建的对象由虚拟机托管。(C# )
-
非托管型代码对象有实际的内存地址,创建的对象必须自己来管理和释放。(C++)
互相调用
-
一般我们如果直接在C++中引用.NET DLL程序会报错的,一般需要我们将.NET DLL生成组件dll 然后再在C++中用,而且需要做些相应的配置。比如开启clr 选项之类的。
-
同样在.NET程序中直接使用C++ DLL也是会有问题的,一般要我们通过interop技术比如Pinvoke之类的来做的。
常见问题
客户端在部分电脑上无法加载指定模块
针对异常情况,做故障分析:
-
C++编译的dll正常,C#编译正常;
-
加载路径也没问题
排除DLL本身的问题后,出现问题的原因就可能是运行环境的问题。
加载的C++生成的DLL,如果其依赖其他DLL,而所依赖的DLL不在当前运行环境,也会出现此种异常。
判断DLL类型
如果可以使用工具,你可以用CorFlags.exe (CorFlags Conversion Tool).aspx) 工具来识别。
我本地CorFlags.exe
所在的路径为
C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools
添加到环境变量中
添加后就能使用了
C++ DLL
1 | CorFlags.exe .\RobotUsbWrapper.dll |
.NET DLL
1 | CorFlags.exe .\RobotpenGateway.dll |
会看到
查询DLL依赖
官方工具
能同时查询C++ DLL和.NET DLL的依赖。
这种方式只能查看依赖,不能查看依赖所在位置,后两种都支持查看依赖位置。
利用vs子自带工具:VS 2017的 x64_x86 交叉工具命令提示符
打开进入cmd模式,找到C++的dll路径,通过命令:
1 | dumpbin /dependents 需要检测的.dll |
如
1 | dumpbin /dependents .\RobotUsbWrapper.dll |
结果
Dependencies(推荐)
能同时查询C++ DLL和.NET DLL的依赖。
支持查看依赖位置。
支持Win10。
这个工具的好处在于不但能查找依赖还能排查出那些依赖的DLL不存在。
如图
https://github.com/lucasg/Dependencies/releases
Dependencies下载地址:
链接:百度网盘 请输入提取码
提取码:psvm
运行其中的DependenciesGui.exe
文件,把DLL拖进去即可。
软件依赖环境:
Microsoft Visual C++ Redistributable
VC下载地址:
链接:百度网盘 请输入提取码
提取码:psvm
安装后无需重启即可生效。
注意
上面缺少的DLL即使安装
Visual C++ 2015-2022 Redistributable
后依旧不行,但是安装Visual C++ 2010 Redistributable
后就可以了。从而我们可以得出一个结论:
Visual C++ 2015-2022 Redistributable
并不是包含2015-2022
所有的DLL。微软这依赖管理真坑人。
Dependency Walker(不推荐)
能同时查询C++ DLL和.NET DLL的依赖。
支持查看依赖位置。
仅适用于winxp/win7/win8,但是不能用于win10,会卡死报错。
Dependency Walker (depends.exe) Home Page
DLL嵌入EXE中
项目地址:https://github.com/MiloszKrajewski/LibZ
使用Nuget图形或者命令下载LibZ.Bootstrap
1 | Install-Package LibZ.Bootstrap -Version 1.2.0 |
然后,配置Post buid 脚本(生成后时间命令行):
1 2 | set LIBZ=$(SolutionDir)packages\LibZ.Bootstrap.1.2.0.0\tools\libz.exe %LIBZ% inject-dll --assembly 星火微课.exe --include *.dll --move |
编译通过后就可以了。这里需要注意的是–assembly后的参数是项目生成的文件名,不是新生成的名称.
但是并不建议这样做:
只有.NET的DLL会被嵌入到EXE中,C++的不会,并且大大增加生成时间。
判断DLL是32位还是64位
使用CorFlags.exe
只能查看.Net
的DLL
1 | CorFlags.exe .\WebrtcSharp.dll | find "32BITREQ" |
在查询结果中
前言
概念
-
动态链接库: 它是一个win32(32位操作系统环境)的概念,以dll为后缀的文件,可以有VC++,C++Builder,Delphi等生成。动态链接库不能调用.net程序集。
-
程序集: 它是一个.net 的概念,可以是dll也可以是exe文件,程序集里面包含了:程序集清单(manifest),类型元数据,Microsoft中间语言(MSIL)代码以及其他资源。
程序集清单包含有:程序集名称,版本信息,区域性信息,强名称信息,程序集文件列表,类型引用信息,引用和依赖程序集信息。
在默认情况下,创建一个程序集,是该应用程序专有的,如果要共享该程序集,必须要加强名称表明该程序集是安全的然后再全局应用程序域缓存(GAC)发布。程序集具有一个语言无关性,也就是说可以用任何一种.net 的语言来开发程序集,然后可以被.net的其他语言使用。例如,可以在 Microsoft Visual C# 中开发程序集,然后在 Microsoft Visual Basic .NET 项目中使用该程序集。
.net程序集可以调用动态链接库。
首先明白一个前提:C#是托管型代码。C++是非托管型代码。
-
托管型代码的对象在托管堆上分配内存,创建的对象由虚拟机托管。(C# )
-
非托管型代码对象有实际的内存地址,创建的对象必须自己来管理和释放。(C++)
互相调用
-
一般我们如果直接在C++中引用.NET DLL程序会报错的,一般需要我们将.NET DLL生成组件dll 然后再在C++中用,而且需要做些相应的配置。比如开启clr 选项之类的。
-
同样在.NET程序中直接使用C++ DLL也是会有问题的,一般要我们通过interop技术比如Pinvoke之类的来做的。
常见问题
客户端在部分电脑上无法加载指定模块
针对异常情况,做故障分析:
-
C++编译的dll正常,C#编译正常;
-
加载路径也没问题
排除DLL本身的问题后,出现问题的原因就可能是运行环境的问题。
加载的C++生成的DLL,如果其依赖其他DLL,而所依赖的DLL不在当前运行环境,也会出现此种异常。
判断DLL类型
如果可以使用工具,你可以用CorFlags.exe (CorFlags Conversion Tool).aspx) 工具来识别。
我本地CorFlags.exe
所在的路径为
C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools
添加到环境变量中
添加后就能使用了
C++ DLL
1 | CorFlags.exe .\RobotUsbWrapper.dll |
.NET DLL
1 | CorFlags.exe .\RobotpenGateway.dll |
会看到
查询DLL依赖
官方工具
能同时查询C++ DLL和.NET DLL的依赖。
这种方式只能查看依赖,不能查看依赖所在位置,后两种都支持查看依赖位置。
利用vs子自带工具:VS 2017的 x64_x86 交叉工具命令提示符
打开进入cmd模式,找到C++的dll路径,通过命令:
1 | dumpbin /dependents 需要检测的.dll |
如
1 | dumpbin /dependents .\RobotUsbWrapper.dll |
结果
Dependencies(推荐)
能同时查询C++ DLL和.NET DLL的依赖。
支持查看依赖位置。
支持Win10。
这个工具的好处在于不但能查找依赖还能排查出那些依赖的DLL不存在。
如图
https://github.com/lucasg/Dependencies/releases
Dependencies下载地址:
链接:https://pan.baidu.com/s/13YYSX-wNLykqFzdx7QDKAA
提取码:psvm
运行其中的DependenciesGui.exe
文件,把DLL拖进去即可。
软件依赖环境:
Microsoft Visual C++ Redistributable
VC下载地址:
链接:https://pan.baidu.com/s/1mhrkDVq1uS-x_pl39m3asg
提取码:psvm
安装后无需重启即可生效。
注意
上面缺少的DLL即使安装
Visual C++ 2015-2022 Redistributable
后依旧不行,但是安装Visual C++ 2010 Redistributable
后就可以了。从而我们可以得出一个结论:
Visual C++ 2015-2022 Redistributable
并不是包含2015-2022
所有的DLL。微软这依赖管理真坑人。
Dependency Walker(不推荐)
能同时查询C++ DLL和.NET DLL的依赖。
支持查看依赖位置。
仅适用于winxp/win7/win8,但是不能用于win10,会卡死报错。
DLL嵌入EXE中
项目地址:https://github.com/MiloszKrajewski/LibZ
使用Nuget图形或者命令下载LibZ.Bootstrap
1 | Install-Package LibZ.Bootstrap -Version 1.2.0 |
然后,配置Post buid 脚本(生成后时间命令行):
1 2 | set LIBZ=$(SolutionDir)packages\LibZ.Bootstrap.1.2.0.0\tools\libz.exe %LIBZ% inject-dll --assembly 星火微课.exe --include *.dll --move |
编译通过后就可以了。这里需要注意的是–assembly后的参数是项目生成的文件名,不是新生成的名称.
但是并不建议这样做:
只有.NET的DLL会被嵌入到EXE中,C++的不会,并且大大增加生成时间。
判断DLL是32位还是64位
使用CorFlags.exe
只能查看.Net
的DLL
1 | CorFlags.exe .\WebrtcSharp.dll | find "32BITREQ" |
在查询结果中
如果32BITREQ
的值为
- 0表示dll是64位
- 1表示dll是32位
使用dumpbin
可以查看.Net
和非.Net
的DLL的位数
1 | dumpbin /headers .\WebrtcSharp.dll | find "machine" |
在查询结果中,如果FILE HEADER VALUES
中有
-
machine (x64)
,表示dll是64位。 -
machine (x86)
,表示dll是32位。
如果32BITREQ
的值为
- 0表示dll是64位
- 1表示dll是32位
使用dumpbin
可以查看.Net
和非.Net
的DLL的位数
1 | dumpbin /headers .\WebrtcSharp.dll | find "machine" |
在查询结果中,如果FILE HEADER VALUES
中有
-
machine (x64)
,表示dll是64位。 -
machine (x86)
,表示dll是32位。