有没有办法提前测试Windows exe是否会因为缺少dll而无法加载?

2024-03-17

如果您尝试在没有任何更新的情况下在 Windows 8.1 上安装 vs2015 Redistributable,它将安装失败。但它会在安装过程中进行足够多的操作,guid 位于注册表中,因此,如果您运行一个程序来检查注册表中是否存在可再发行组件,您将通过该检查。

如果你随后尝试运行一个用 vs2015 编译的程序,该程序需要一些无法安装的 dll,你会看到一个弹出窗口,显示“程序无法启动,因为......”你知道该怎么做。

我正在开发一个存在此问题的安装程序(使用 NSIS),并且我正在尝试找到一种方法来在运行 .exe 并获取弹出窗口之前检测 dll 丢失问题。是否有任何我可以运行的命令行工具或我可以调用的任何 NSIS 函数可以在问题发生之前提示我解决这个问题?

或者甚至有一种方法可以检查 vs2015 可再发行组件是否正确安装? (无需检查可再发行文件中的每个文件是否存在,因为我不知道它们是什么。)

寻找解决整体问题的任何想法,不一定要专门通过这一检查。我预计可再发行组件可能会因各种原因而无法安装。


我相信 VS2015 是在没有 WinSxS 的情况下在 System32 中安装 .DLL 的版本之一,因此您也许可以检查 vcruntime140.dll 和 msvcp140.dll 是否在$SysDir.

如果您担心它可能是部分安装,您可以查看是否可以加载它(假设您的安装程序与您正在安装的内容匹配):

!include LogicLib.nsh
System::Call 'KERNEL32::LoadLibrary(t "$SysDir\msvcr100.dll")p.r0'
${If} $0 P<> 0
    DetailPrint "I was able to load the MSVC 2010 run-time DLL"
${Else}
    DetailPrint "Ooops"
${EndIf}

这可能被认为是有点黑客行为,但它可能足以满足您的需求。依赖步行者 http://www.dependencywalker.com/会告诉您要查找哪些 DLL。

您也可以致电MsiGetProductInfo如果您愿意,可以使用 NSIS:

!define MSVC2005_X86REDIST_PRODUCTCODE {A49F249F-0C91-497F-86DF-B2585E8E76B7}
!define MSVC2008_X86REDIST_PRODUCTCODE {FF66E9F6-83E7-3A3E-AF14-8DE9A809A6A4}
!define MSVC2010_X86REDIST_PRODUCTCODE {196BB40D-1578-3D01-B289-BEFC77A11A1E}
!define MSVC2010SP1_X86REDIST_PRODUCTCODE {F0C3E5D1-1ADE-321E-8167-68EF0DE699A5}
!define MSVC2010_AMD64REDIST_PRODUCTCODE {DA5E371C-6333-3D8A-93A4-6FD5B20BCC6E}
!define MSVC2010SP1_AMD64REDIST_PRODUCTCODE {1D8E6291-B0D5-35EC-8441-6616F567A0F7}

!define MSVCREDIST_PRODUCTCODE ${MSVC2010_X86REDIST_PRODUCTCODE} ; I don't have VS2015 redist installed on this machine so I could not test it.
!include LogicLib.nsh
System::Call 'MSI::MsiGetProductInfo(t "${MSVCREDIST_PRODUCTCODE}", t "ProductName", t"?"r1, *i${NSIS_MAX_STRLEN})i.r0'
${If} $0 == 0
    DetailPrint "ProductName: $1"
    System::Call 'MSI::MsiGetProductInfo(t "${MSVCREDIST_PRODUCTCODE}", t "AssignmentType", t"?"r1, *i${NSIS_MAX_STRLEN})i.r0'
    DetailPrint "AssignmentType: $1"
    System::Call 'MSI::MsiGetProductInfo(t "${MSVCREDIST_PRODUCTCODE}", t "PackageCode", t"?"r1, *i${NSIS_MAX_STRLEN})i.r0'
    DetailPrint "PackageCode: $1"
    System::Call 'MSI::MsiGetProductInfo(t "${MSVCREDIST_PRODUCTCODE}", t "VersionString", t"?"r1, *i${NSIS_MAX_STRLEN})i.r0'
    DetailPrint "VersionString: $1"
${Else}
    DetailPrint "Not registered with Windows Installer"
${EndIf}

这篇博文 https://blogs.msdn.microsoft.com/astebner/2007/01/16/mailbag-how-to-detect-the-presence-of-the-vc-8-0-runtime-redistributable-package/说 Visual Studio 2005 使用MsiQueryProductState如果您不需要更多详细信息,这可能是一个不错的简单替代方案:

!define INSTALLSTATE_DEFAULT 5
System::Call 'MSI::MsiQueryProductState(t "${MSVCREDIST_PRODUCTCODE}")i.r0'
${If} ${INSTALLSTATE_DEFAULT} = $0
    DetailPrint "Installed"
${Else}
    DetailPrint "Not installed"
${EndIf}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

有没有办法提前测试Windows exe是否会因为缺少dll而无法加载? 的相关文章

  • 如何在多线程C++ 17程序中交换两个指针?

    我有两个指针 pA 和 pB 它们指向两个大的哈希映射对象 当pB指向的哈希图完全更新后 我想交换pB和pA 在C 17中 如何快速且线程安全地交换它们 原子 我是 c 17 的新手 2个指针的原子无等待交换可以通过以下方式实现 inclu
  • 为什么pow函数比简单运算慢?

    从我的一个朋友那里 我听说 pow 函数比简单地将底数乘以它的指数的等价函数要慢 例如 据他介绍 include
  • IdentityServer 4 对它的工作原理感到困惑

    我阅读和观看了很多有关 Identity Server 4 的内容 但我仍然对它有点困惑 因为似乎有很多移动部件 我现在明白这是一个单独的项目 它处理用户身份验证 我仍然不明白的是用户如何注册它 谁存储用户名 密码 我打算进行此设置 Rea
  • 如何在C(Linux)中的while循环中准确地睡眠?

    在 C 代码 Linux 操作系统 中 我需要在 while 循环内准确地休眠 比如说 10000 微秒 1000 次 我尝试过usleep nanosleep select pselect和其他一些方法 但没有成功 一旦大约 50 次 它
  • 当一组凭据下的计划任务启动的进程在另一组凭据下运行另一个程序时,Windows 是否有限制

    所以我有一个简单的例子 其中我有应用程序 A 它对用户 X 本地管理员 有一些硬编码的凭据 然后它使用硬编码的绝对路径启动带有这些凭据的应用程序 B A 和 B 以及 dotnet 控制台应用程序 但是它们不与控制台交互 只是将信息写入文件
  • 从客户端访问 DomainService 中的自定义对象

    我正在使用域服务从 Silverlight 客户端的数据库中获取数据 在DomainService1 cs中 我添加了以下内容 EnableClientAccess public class Product public int produ
  • 告诉 Nancy 将枚举序列化为字符串

    Nancy 默认情况下在生成 JSON 响应时将枚举序列化为整数 我需要将枚举序列化为字符串 有一种方法可以通过创建来自定义 Nancy 的 JSON 序列化JavaScript 原始转换器 https github com NancyFx
  • 将 Long 转换为 DateTime 从 C# 日期到 Java 日期

    我一直尝试用Java读取二进制文件 而二进制文件是用C 编写的 其中一些数据包含日期时间数据 当 DateTime 数据写入文件 以二进制形式 时 它使用DateTime ToBinary on C 为了读取 DateTime 数据 它将首
  • 类型约束

    我有以下类层次结构 class Header IEnumerable
  • 如何在 C 中安全地声明 16 位字符串文字?

    我知道已经有一个标准方法 前缀为L wchar t test literal L Test 问题是wchar t不保证是16位 但是对于我的项目 我需要16位wchar t 我还想避免通过的要求 fshort wchar 那么 C 不是 C
  • 为什么我的单选按钮不起作用?

    我正在 Visual C 2005 中开发 MFC 对话框应用程序 我的单选按钮是 m Small m Medium 和 m Large 它们都没有在我的 m Summary 编辑框中显示应有的内容 可能出什么问题了 这是我的代码 Pizz
  • WPF DataGridTemplateColumn 组合框更新所有行

    我有这个 XAML 它从 ItemSource 是枚举的组合框中选择一个值 我使用的教程是 http www c sharpcorner com uploadfile dpatra combobox in datagrid in wpf h
  • 用于推送通知的设备令牌

    我正在实施推送通知服务 我需要创建一个数据库来存储 4 个移动平台的所有设备令牌 我想根据他们的平台 iOS Android BlackBerry WP7 来组织它们 但是有什么方法可以区分平台 这样如果我只想向 Android 用户发送消
  • Unity:通过拦截将两个接口注册为一个单例

    我有一个实现两个接口的类 我想对该类的方法应用拦截 我正在遵循中的建议Unity 将两个接口注册为一个单例 https stackoverflow com questions 1394650 unity register two inter
  • 将数组作为参数传递

    如果我们修改作为方法内参数传递的数组的内容 则修改是在参数的副本而不是原始参数上完成的 因此结果不可见 当我们调用具有引用类型参数的方法时 会发生什么过程 这是我想问的代码示例 using System namespace Value Re
  • 在 Windows Phone silverlight 8.1 上接收 WNS 推送通知

    我有 Windows Phone 8 1 silverlight 应用程序 我想使用新框架 WNS 接收通知 我在 package appxmanifest 中有
  • 可访问性不一致:参数类型的可访问性低于方法

    我试图在两个表单之间传递一个对象 基本上是对当前登录用户的引用 目前 我在登录表单中有一些类似的内容 private ACTInterface oActInterface public void button1 Click object s
  • 如何在richtextbox中使用多颜色[重复]

    这个问题在这里已经有答案了 我使用 C windows 窗体 并且有 richtextbox 我想将一些文本设置为红色 一些设置为绿色 一些设置为黑色 怎么办呢 附图片 System Windows Forms RichTextBox有一个
  • 使用 C 在 OS X 中获取其他进程的 argv

    我想获得其他进程的argv 例如ps 我使用的是在 Intel 或 PowerPC 上运行的 Mac OS X 10 4 11 首先 我阅读了 ps 和 man kvm 的代码 然后编写了一些 C 代码 include
  • 不区分大小写的字符串比较 C++ [重复]

    这个问题在这里已经有答案了 我知道有一些方法可以进行忽略大小写的比较 其中涉及遍历字符串或一个good one https stackoverflow com questions 11635 case insensitive string

随机推荐