Почему System :: Call возвращает «0» при запуске 32-разрядного установщика на 32-разрядном компьютере, но при запуске на 64-разрядном компьютере, возвращается пустое значение в NSIS - PullRequest
0 голосов
/ 25 января 2019

Я создал 32-разрядный установщик, использующий NSIS, и он должен работать как на 32-разрядных, так и на 64-разрядных компьютерах.

Приведенный ниже код работает нормально на 32-битном компьютере, где он вызывает DLL (Profile.dll) с помощью System :: Call и соответствующей функции IsSplashScreenDisabled (). Эта функция возвращает false и показывает окно сообщения. Работает как положено.

Но тот же установщик, когда я запускаю на 64-битной машине, System :: Call не возвращает "0", вместо этого он показывает пустое "". Поэтому я не получаю окно сообщения.

А также, если я заменил «$ PROGRAMFILES32» на «$ PROGRAMFILES64», то он также показывает пустое «» и не показывает окно сообщения.

Итак, здесь мне нужны ваши предложения или мысли о том, почему System :: Call работает по-разному с 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;
}

1 Ответ

0 голосов
/ 11 февраля 2019

Способ синтаксического анализа строки System::Call имеет ошибку, если строка содержит (..), она будет анализировать это как параметры функции и не сможет загрузить .DLL, и вызов не будет выполнен.В 64-битной Windows $ ProgramFiles32 содержит (x86) как часть пути, и это вызывает ошибку.

Существует два способа обойти это:

A)

Используйте комбинацию 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}
...