如何摆脱“缺少DLL”的问题?


15

我使用Visual C ++ 2015和OpenGL制作了一些游戏。当我在计算机上运行它时没有问题,但是当我在其他计算机上运行它时,它表明缺少某些DLL。我想知道如何确保下次不会发生这种情况,我应该考虑些什么,以便避免文件丢失的问题?


8
首先,请确保您正在构建发行版本。
user253751'3

3
如果您要绝对确定VS本身没有依赖性-但是它有其自身的缺点-在代码生成设置中,您可以选择使用多线程/多线程调试(用于调试版本)而不是MT DLL / MT调试DLL。它的确增加了可执行文件的大小,并且以这种方式编译的二进制文件不会从运行时dll更新中受益。但这取决于您。从好的方面来说,您的可执行文件将没有“外部”依赖性。我不会将其发布为答案,因为这不是解决您的问题的方法,而只是解决方法。
Gizmo

@Gizmo的解决方法仍然是一个答案,并且注释是临时的,用于澄清其所属的帖子,并且可能被删除。因此,如果有用,则应将其发布为答案。
user1306322

好吧 那我将其发布为答案。
Gizmo

Answers:


22

您需要在要运行可执行文件的任何计算机上安装Visual Studio版本的可再发行文件,例如VS2015的https://www.microsoft.com/zh-cn/download/details.aspx?id=48145。您可能还需要RedX用于DirectX或其他组件。

应用程序的安装程序通常会为所有依赖项安装所有可再发行文件。您可以使用InnoSetup,NSIS,WIX或其他各种工具来制作这样的安装程序。

可以使不需要任何可再发行的可执行文件成为可能,但是您只能使用Windows核心功能的子集,这通常不足以制作任何有意义的游戏或大型应用程序。安装程序本身就是不需要任何依赖项即可运行的应用程序的示例。


可以使用VS来构建这样的安装程序吗?我以为我曾经在项目设置中看到过一种叫做OneClick的东西。
user1306322

@ user1306322:绝对的,Gizmo在问题的评论中提到了一种解决方案。只是链接到哪个运行时/ DLL的问题。默认设置使您可以链接到特定于版本的CRT DLL,但可以通过将链接器选项中的内容更改来进行更改。只需链接MSVCRT.DLL(包含在Windows本身中)而不是MSVCPxxx.DLL(Visual Studio发行版中包含的特定于版本的版本)即可。
肖恩·米德迪奇

或者,如果您要构建一个完整的安装程序,则基本上就是WIX。这是一个典型的,过于繁琐的XML繁重的Microsoft最糟糕的尝试,但是它可以工作。过去也有“安装程序项目”,尽管我认为这些项目自2013年或2015
。– Sean Middleditch

7

我使用Dependency Walker来跟踪丢失的DLL:

Dependency Walker对解决与加载和执行模块有关的系统错误也非常有用。Dependency Walker检测到许多常见的应用程序问题,例如缺少模块,无效模块,导入/导出不匹配,循环依赖项错误,模块的机器类型不匹配以及模块初始化失败。


VS中还有一个编译时选项可以静态链接 DLL:

  • 静态链接意味着DLL包含在EXE文件中。
  • 静态链接会增加EXE文件的大小。
  • 静态链接意味着将始终使用此版本的DLL。
  • 但是,静态链接也意味着您永远不会遇到缺少DLL的问题。

1
依赖行者已经很老了。它不再正确地模仿Windows的用于加载DLL的机制。通常会导致有关无法找到DLL的虚假消息。
jpmc26,2017年

并且依赖项的许可证中可能禁止静态链接。
KeyWeeUsr

6

对于Visual C ++,您可以选择几种方式来处理重新分发:从安装程序运行EXE(具有管理员权限),将MSM合并模块与MSI安装程序一起使用,甚至并排DLL。看到详细信息, MSDN

更大的问题是OpenGL。Windows随附的唯一OpenGL版本是OpenGL 1.5软件渲染器。其他任何情况都需要安装第三方ICD。

这是许多Windows游戏使用DirectX的原因之一,因为它包含在操作系统中。请参阅面向游戏开发人员的Direct3D 11部署,不是直接安装


1
OpenGL建议已过时-每个现代图形驱动程序均随附最新的OpenGL ICD。
user253751'3

我个人必须在只有一年的机器上安装openGL DLL
Gnemlock

@Gnemlock在所述使用年限的计算机上重新安装Windows后,您可能是正确的。在安装了NVIDIA,AMD或Intel的官方驱动程序包之后,您是否仍然看到此问题?
Damian Yerrick '17

2
@Gnemlock-如果您手动安装OpenGL DLL,那么您所做的事情简直是错误的。如果您实际上是说“安装GPU供应商的驱动程序”,那也正是immibis所说的。
Maximus Minimus'3

@Gnemlock-啊,所以与现实世界无关。感谢您清理。
Maximus Minimus

1

免责声明:这是一种解决方法,不是您的答案的解决方案,但仍然是非常可行的可能性。

如果您要绝对确定VS本身不存在依赖关系-但它有其自身的缺点-在代码生成设置中,您可以选择使用多线程(MT)/多线程调试(MD)(用于调试版本) ),而不是MT DLL(MTd)/ MT调试DLL(MDd)。

在此处输入图片说明

有什么缺点?

  • 它确实增加了可执行文件的大小和二进制文件(尽管如果您正在制作游戏,这可能可以忽略不计)
  • 以这种方式编译的文件将不会从运行时dll更新中受益。(例如,如果Microsoft发布VC ++ 2015 SP2,SP3,SP4等。)但这取决于您。
  • 因为您不重用现有/已加载的代码(DLL),所以更多的RAM使用量(也可以忽略不计)
  • 您需要确保链接的所有库都是针对相同的运行时编译的,否则链接可能会失败,或者可能会发生有趣的运行时错误(可能不会,但是我确实在一个已更新为最新的VS)

优点是什么?

  • 您的可执行文件将不具有VS本身的“外部”依赖关系(没有msvc * .dll要求)。
  • 有人认为这是性能的提高,因为您消除了DLL调用的开销,尽管从理论上讲这是正确的,但实际中的改进可忽略不计

检查此链接以获得更详尽的解释以及使用静态运行时可能遇到的陷阱。

另一个解决方法是将所有必需的DLL放在您的二进制文件所在的位置。您的应用程序不会从更新(运行时库)中受益,仅此而已。

真正的解决方案是以发布/非调试dll模式(MTd)分发应用程序,并提供正确的VC ++可再发行安装程序(以及您可能使用的任何其他库安装程序,例如OpenAL,DirectX9,PhysX),然后让用户运行在运行您的应用程序之前(如其他答案所指出)。

还要确保让用户知道他/她可能需要更新他/她的GPU驱动程序(因为这些驱动程序也包含许多应用程序的多个运行时,例如OpenGL,Vulcan)。


0

我的解决方案是将导致错误的DLL复制并粘贴到Visual Studio中.sln文件所在的文件夹中。在本#include节之后,我写#pragma comment (lib, "lost DLL name with .dll")并解决了它!

注意:我解决了第三方库(vulkan api)DLL遇到的问题。也许还不知道,但90%的运气会很好:)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.