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

谁说胖子不能爱 提交于 2019-12-11 00:00:01

问题


If you try and install the vs2015 redistributable on windows 8.1 without any updates, it will fail to install. But it will get far enough into the install process that the guid is in the registry so if you run a program that checks for the existence of the redistributable in the registry, you'll get past that check.

If you then try and run a program compiled with vs2015 that requires some of the dlls that failed to install, you'll get a popup that says "The program can't start because..." you know the drill.

I'm working on an installer (with NSIS) that is having this problem, and I'm trying to find a way to detect the dll missing problem before I run the .exe and get the popup. Is there any command line tool I can run or any NSIS function I can call that will clue me into this problem before it happens?

Or even a way to check if the vs2015 redistributable installed correctly? (without having to check for the existence of every single file in the redistributable, because I don't know what they all are.)

Looking for any ideas to solve the overall problem, not necessarily to specifically get past this one check. I expect there can be all sorts of ways the redistributable can fail to install.


回答1:


I believe VS2015 is one of the versions that installs the .DLLs in System32 without WinSxS so you could perhaps just check if vcruntime140.dll & msvcp140.dll is in $SysDir.

If you are worried that it might be a partial install you could see if you can load it (assuming your installer matches the bitness of the thing you are installing):

!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}

This might be considered a bit of a hack but it might be enough for your needs. Dependency Walker will tell you which DLLs to look for.

You can also call MsiGetProductInfo with NSIS if you wish:

!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}

This blog post says that Visual Studio 2005 uses MsiQueryProductState and that is probably a nice simple alternative if you don't need any more details:

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


来源:https://stackoverflow.com/questions/44264521/is-there-a-way-to-test-beforehand-if-a-windows-exe-will-fail-to-load-because-of

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!