编译了几个.dll使用visual studio 2015,并试图部署在一些旧的Windows 7/64位上 . 试图猜测应用程序启动和复制MSVCP140.DLL和VCRUNTIME140.DLL需要哪些dll - 但是应用程序无法加载vs2015 dll . 开始分析什么是错误 - 并且依赖者walker显示来自跟随dll的依赖:
API-MS-WIN-CRT-MATH-L1-1-0.DLL
API-MS-WIN-CRT-HEAP-L1-1-0.DLL
API-MS-WIN-CRT-CONVERT-L1-1-0.DLL
API-MS-WIN-CRT-STRING-L1-1-0.DLL
API-MS-WIN-CRT-STDIO-L1-1-0.DLL
API-MS-WIN-CRT-RUNTIME-L1-1-0.DLL
API-MS-WIN-CRT-FILESYSTEM-L1-1-0.DLL
API-MS-WIN-CRT-TIME-L1-1-0.DLL
这是特别令人惊讶的,因为我最好的理解CRT负责启动dll / exe,它不提供任何更高级别的服务 .
好的,试图弄清楚如何摆脱它们或至少最小化 .
找到一篇文章:https://blogs.msdn.microsoft.com/vcblog/2015/03/03/introducing-the-universal-crt/
它提到了发布静态库 - 所以我认为我可以链接它们并摆脱* L1-1-0.DLL *依赖地狱,但无论我尝试过什么 - 我都没有成功 . 我试着对libvcruntime.lib,libucrt.lib,LIBCMT.LIB链接,尝试使用连接选项“/nodefaultlib:vcruntime.lib”禁用,甚至试图添加包括目录$(UniversalCRT_IncludePath),同时还覆盖了一些定义的,因为我试图猜测它们是有效的 - 我的尝试都没有帮助 .
作为一个中间解决方案,我回归到使用Visual Studio 2013,其中CRT dll只有两个:msvcp120.dll,msvcr120.dll .
当然,您可能会建议安装Visual Studio 2015运行时,但我们的要求之一是支持独立可执行文件 - 无需任何安装即可运行 - 因此现在无法进行额外安装 .
除了等待Visual Studio 2017到货之外,你能推荐我吗?
4 回答
我能够通过设置
C/C++ > Code Generation > Runtime Library
编译器选项来解决这个问题对于调试:从
/MDd
到/MTd
For Release:从
/MD
到/MT
这删除了所有
API-MS-WIN-CRT-*
和运行时dll引用,并导致所有CRT代码静态链接 .有关新VS2015通用CRT(动态和静态)的详细信息,请访问:https://msdn.microsoft.com/en-us/library/abx4dbyh.aspx
我也正在努力将一个解决方案与多个组件/项目库依赖关系静态链接,从MSVCRT,UCRT和内核的各个部分导入函数 . 希望得到的EXE可以只是复制到需要它的地方(它不是可以证明完整的MSI安装的产品) .
几乎放弃后我发现最好的解决方案是遵循Universal C Runtime announcement中隐藏的指导原则,具体来说:
只需删除您尝试的所有"special"链接器选项,回退到/ MT | / MD(多线程CRT DLL发布|调试)运行时库选项,它可以在任何地方使用,例如较新的Windows 10工作站,2012 R2服务器和Windows 7) . 只需像微软告诉我们那样安装/重新发布MSVCRT (VC_Redist*.exe)和KB2999226 (UCRT via Windows Update),因为他们也说:
因此,逻辑上我们的C解决方案为客户添加的唯一额外部署依赖是MSVCRT,因为UCRT应该已经存在于最新/维护良好的机器上 . 当然它增加了一点不确定性;你不能只是复制EXE并在任何机器上运行,无论好坏 .
如果您像MSI一样生成一个像样的部署包,那么当您拥有像WIX这样的工具时,可以直接包含它 . 另外要注意的是,从最近的SDK开始,你可以在本地包含40多个DLL,但这不符合安全更新原则,所以我不会这样做 .
这实际上是唯一受支持的方式,see another example here . 本文还建议我们链接"mincore_downlevel.lib"这是一个重要提示,对于您是否得到这些"api-ms-win*"错误的DLL错误至关重要 . 例如:
Project SDK版本设置为10,与mincore.lib链接=仅在Windows 10上运行,但不在8.1 / 2012 R2或Windows 7/2008 R2服务器上运行 .
Project SDK版本设置为8.1,与mincore.lib链接=在Windows 10和8.1 / 2012 R2服务器上运行,但不在Windows 7/2008 R2服务器上运行 .
Project SDK version set to 10, link with mincore_downlevel.lib = Runs on all!
综上所述:
不要静态链接,保留在项目设置中选择的默认DLL C运行时 .
您不需要旧的SDK,可以使用最新的Windows 10 SDK进行开发,但是如果要支持较旧的Windows版本,则必须链接"mincore_downlevel.lib"而不是"mincore.lib" .
为了便于使用,请将它添加到targetver.h或stdafx.h中,它也会记录您的选择(删除另一行):
我发现运行Visual Studio 2015中构建的应用程序所需的运行时DLL太过挣扎了 .
在这里,我发现了以下允许VS-2015构建的应用程序运行的东西 .
从https://www.microsoft.com/en-us/download/details.aspx?id=52685下载可再发行组件
放置msvcp140d.dll,vccorlib140d.dll,vcruntime140d.dll和ucrtbased.dll .
注意:根据系统处理器的体系结构(x86,x64 ..)放置dll版本 .
(2016年10月11日更新) .
通过静态链接它可以摆脱通用CRT,我稍后会介绍它,但是让我们来看看你是否继续使用通用CRT .
根据文章https://blogs.msdn.microsoft.com/vcblog/2015/03/03/introducing-the-universal-crt/ - 可以使用以下文件夹中的通用crt dll distributables启动您的应用程序:
C:\Program Files (x86)\Windows Kits\10\Redist\ucrt
列表中共有41个文件,总共1.8 Mb . (64位平台的示例)
当然这还不够,你还需要来自以下文件夹的vcruntime140.dll和msvcp140.dll:
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\redist\x64\Microsoft.VC140.CRT
因此,除了您的应用程序之外,您将再运送43个额外的dll .
也可以在你的应用程序中静态编译ucrt库,之后你不需要43个dll - 但是否链接后是否为静态链接 - 取决于你的应用程序 - 有多少dll和哪些api正在使用中 . 通常在ucrt链接到两个不同的dll之后,它们不一定彼此共享相同的全局 - 这可能导致错误 .
你需要链接vcruntime.lib / msvcrt.lib,但这还不够 - 还有额外的
_VCRTIMP=
和_ACRTIMP=
定义,需要禁止从ucrt中提取函数 .如果你正在使用premake5,你可以像这样配置你的项目:
其次是:
Microsoft没有记录定义 - 因此未来可能会发生变化 .
除了您自己的项目,您还需要重新编译项目中使用的所有静态库 .
至于boost库 - 我也设法使用b2.exe boostrapper编译boost
boost>call b2 threading=multi toolset=msvc-14.0 address-model=64 --stagedir=release_64bit --build-dir=intermediate_64but release link=static,shared --with-atomic --with-thread --with-date_time --with-filesystem define=_VCRTIMP= define=_ACRTIMP=
在解决链接问题时 - 请注意因为
dllimport
关键字用法而导致未解析的__imp*
函数名称 - 如果链接到libvcruntime.lib,则不应该有任何__imp*
引用 .