我已创建使用NSIS一个32位的安装程序,并应在32位或64位计算机上运行。
以下代码是在32位机,其中它被调用使用系统::调用的DLL(Profile.dll)工作正常和相应的功能IsSplashScreenDisabled()。该函数返回false,并显示该消息框。它工作正常。
但是,当我在64位机,系统::调用没有返回运行相同的安装程序“0”,而不是它显示空白的“”。所以,我没有得到的消息框。
而且如果我改变“$ PROGRAMFILES32”到“$ PROGRAMFILES64”,那么也它显示空白“”,而不是显示消息框。
所以在这里我需要你的建议或为什么系统::呼叫与32位/ 64位安装程序的工作不同,在32位或64位计算机的想法。
!include LogicLib.nsh
InstallDir $PROGRAMFILES32\MyAppTest
Page components
Page directory
Page instfiles
UninstPage uninstConfirm
UninstPage instfiles
Section
SetOutPath $INSTDIR
File E:\TestNullSoft\Profile.dll
System::Call 'KERNEL32::AddDllDirectory(w "$INSTDIR")'
System::Call "$INSTDIR\Profile.dll::IsSplashScreenDisabled() i.r0 ?e"
Pop $1
${If} $0 = 0
MessageBox MB_OK|MB_ICONEXCLAMATION "Splash Screen Is Disabled.$\r$\nRolling back the installation..." IDOK
${EndIf}
SectionEnd
下面是IsSplashScreenDisabled()函数
BOOL IsSplashScreenDisabled()
{
BOOL bResult = FALSE;
DWORD dwSplashScreen(0);
RegistryObj regObj(SPE_DALI_SETTINGS_REG_PATH);
if (regObj.Get(SPE_SETTINGS_ENABLE_SPLASH_SCREEN, dwSplashScreen))
{
bResult = (BOOL) !dwSplashScreen;
}
return bResult;
}
该方法System::Call
解析字符串有一个缺陷,如果字符串包含(..)
它将解析,作为函数的参数,它无法加载.dll和调用失败。在64位Windows $ ProgramFiles32包含(x86)
作为路径的一部分,这将触发该漏洞。
有两种方法可以解决此问题:
一种)
使用SetOutPath
和AddDllDirectory
的组合,以确保该.dll可以从相对路径加载:
SetOutPath $InstDir
System::Call 'KERNEL32::AddDllDirectory(w "$INSTDIR")'
File MyFile.dll
System::Call 'MyFile::MyFunction()i.r0'
SetOutPath
使得路径当前目录和AddDllDirectory
添加目录的有效目录,从加载的列表。
B)
手动加载.dll和直接调用地址:
SetOutPath $InstDir
System::Call 'KERNEL32::AddDllDirectory(w "$INSTDIR")'
File MyFile.dll
System::Call 'KERNEL32::LoadLibrary(t "$InstDir\MyFile.dll")p.r1'
${If} $1 P<> 0
System::Call 'KERNEL32::GetProcAddress(pr1,m "MyFunction")p.r2'
${If} $2 P<> 0
System::Call '::$2()i.r0'
${EndIf}
System::Call 'KERNEL32::FreeLibrary(pr1)'
${EndIf}