首页 文章

Visual Studio 2015运行时依赖或如何摆脱Universal CRT?

提问于
浏览
18

编译了几个.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 回答

  • 5

    我能够通过设置 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

  • 3

    我也正在努力将一个解决方案与多个组件/项目库依赖关系静态链接,从MSVCRT,UCRT和内核的各个部分导入函数 . 希望得到的EXE可以只是复制到需要它的地方(它不是可以证明完整的MSI安装的产品) .

    几乎放弃后我发现最好的解决方案是遵循Universal C Runtime announcement中隐藏的指导原则,具体来说:

    出于性能和可维护性的原因,我们强烈建议不要使用Visual C库的静态链接

    只需删除您尝试的所有"special"链接器选项,回退到/ MT | / MD(多线程CRT DLL发布|调试)运行时库选项,它可以在任何地方使用,例如较新的Windows 10工作站,2012 R2服务器和Windows 7) . 只需像微软告诉我们那样安装/重新发布MSVCRT (VC_Redist*.exe)KB2999226 (UCRT via Windows Update),因为他们也说:

    Universal CRT是Windows操作系统的一个组件 . 它作为Windows 10的一部分包含在内,从1月份技术预览版开始,可通过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中,它也会记录您的选择(删除另一行):

    // Libraries
    #pragma comment(lib, "mincore.lib")             // Lowest OS support is same as SDK
    #pragma comment(lib, "mincore_downlevel.lib")   // Support OS older than SDK
    
  • 1

    我发现运行Visual Studio 2015中构建的应用程序所需的运行时DLL太过挣扎了 .

    在这里,我发现了以下允许VS-2015构建的应用程序运行的东西 .

    注意:根据系统处理器的体系结构(x86,x64 ..)放置dll版本 .

  • 20

    (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,你可以像这样配置你的项目:

    defines { "_VCRTIMP="}
    linkoptions { "/nodefaultlib:vcruntime.lib" }
    links { "libvcruntime.lib" }
    

    其次是:

    defines { "_ACRTIMP="}
    linkoptions { "/nodefaultlib:msvcrt.lib" }
    links { "libcmt.lib" }
    

    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* 引用 .

相关问题