有没有办法预先测试 windows exe 是否会因为缺少 dll 而加载失败?

Is there a way to test beforehand if a windows exe will fail to load because of missing dlls?

如果您尝试在 windows 8.1 上安装 vs2015 可再发行组件而不进行任何更新,它将无法安装。但是安装过程中 guid 在注册表中已经足够了,所以如果你 运行 一个检查注册表中是否存在可再发行组件的程序,你将通过该检查。

如果您然后尝试 运行 使用 vs2015 编译的程序需要一些安装失败的 dll,您将看到一个弹出窗口,显示 "The program can't start because..." 你知道这个练习。

我正在开发一个有这个问题的安装程序(使用 NSIS),我正在尝试找到一种方法来检测 dll 丢失问题,然后再 运行 .exe 并获取弹出。有没有我可以使用的命令行工具 运行 或者我可以调用的任何 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} [=10=] P<> 0
    DetailPrint "I was able to load the MSVC 2010 run-time DLL"
${Else}
    DetailPrint "Ooops"
${EndIf}

这可能会被认为是一个 hack,但它可能足以满足您的需求。 Dependency Walker 会告诉您要查找哪些 DLL。

如果您愿意,您也可以通过 NSIS 调用 MsiGetProductInfo

!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} [=11=] == 0
    DetailPrint "ProductName: "
    System::Call 'MSI::MsiGetProductInfo(t "${MSVCREDIST_PRODUCTCODE}", t "AssignmentType", t"?"r1, *i${NSIS_MAX_STRLEN})i.r0'
    DetailPrint "AssignmentType: "
    System::Call 'MSI::MsiGetProductInfo(t "${MSVCREDIST_PRODUCTCODE}", t "PackageCode", t"?"r1, *i${NSIS_MAX_STRLEN})i.r0'
    DetailPrint "PackageCode: "
    System::Call 'MSI::MsiGetProductInfo(t "${MSVCREDIST_PRODUCTCODE}", t "VersionString", t"?"r1, *i${NSIS_MAX_STRLEN})i.r0'
    DetailPrint "VersionString: "
${Else}
    DetailPrint "Not registered with Windows Installer"
${EndIf}

This blog post 表示 Visual Studio 2005 使用 MsiQueryProductState 如果您不需要更多详细信息,这可能是一个不错的简单替代方案:

!define INSTALLSTATE_DEFAULT 5
System::Call 'MSI::MsiQueryProductState(t "${MSVCREDIST_PRODUCTCODE}")i.r0'
${If} ${INSTALLSTATE_DEFAULT} = [=12=]
    DetailPrint "Installed"
${Else}
    DetailPrint "Not installed"
${EndIf}