如何在NullSoft静默安装期间检查可用空间?

时间:2009-06-12 21:35:49

标签: windows installer nsis diskspace

在静默安装模式下,系统不会询问用户PageEx directory的安装目标,因此永远不会调用DirVerifyGetInstDirError函数。

这也适用于硬编码安装目标的安装(一个坏主意),原因与上述相同:PageEx directory永远不会被调用。

3 个答案:

答案 0 :(得分:2)

您的示例代码没问题,但在Win9x上调用$ {DriveSpace}可能会失败。我还删除了指定节id的

的需要
!define APPNAME "CalcEnoughSpace"
name "${APPNAME}"
outfile "$%temp%\${APPNAME}.exe"
ShowInstDetails show
RequestExecutionLevel user
installdir "$Temp"
AllowRootDirInstall true

!include Sections.nsh
!include LogicLib.nsh

Function .onInit
push $instdir
call VerifyFreeSpace
pop $0
${If} $0 < 1
    MessageBox mb_iconstop "Not enough free space!"
${EndIf}
FunctionEnd

page instfiles

Section !a
AddSize 10000
SectionEnd
Section /o b
AddSize 10000
SectionEnd

SectionGroup grp
Section c
AddSize 10000
SectionEnd
SectionGroupEnd



Function VerifyFreeSpace
System::Store s
pop $0 ;path to check
Push 0 ;default to no
System::Call 'kernel32::GetDiskFreeSpaceEx(tr0,*l.r1,*l,*l)i.r2'
${If} $2 < 1 
    StrCpy $0 $0 3
    System::Call 'kernel32::GetDiskFreeSpace(tr0,*i.r1,*i.r2,*i.r3,*i)i.r4'
    IntCmpU $4 0 ret 
    IntOp $1 $1 * $2
    System::Int64Op $1 * $3
    pop $1  
${EndIf}
System::Int64Op $1 / 1024 ;to kb
pop $1
StrCpy $4 0 ;size
StrCpy $2 0 ;section idx
loop:
    ClearErrors
    SectionGetFlags $2 $3
    IfErrors testspace
    IntOp $3 $3 & ${SF_SELECTED}
    ${If} $3 <> 0
        SectionGetSize $2 $3
        IntOp $4 $4 + $3
        ${EndIf}
    IntOp $2 $2 + 1
    goto loop
testspace:
pop $2 ;throw away default return value
System::Int64Op $1 > $4
ret:
System::Store l
FunctionEnd

我只进行了有限的测试,希望没有错误:)

答案 1 :(得分:1)

我在NSIS中编写了一个名为CheckFreeSpace的函数来执行此操作。不幸的是,它有以下限制:

  • 要计算安装中所有部分的大小,您必须通过了解每个部分ID写入的每个变量来修改CheckFreeSpace以添加每个部分。我无法找到一种迭代将使用NSIS安装的所有部分的方法。
  • 必须计算安装驱动器,因为${DriveSpace}需要驱动器号,而不是任意目录的路径。驱动器号字符串使用StrCpy $instdrive $INSTDIR 3计算。如果$INSTDIR变量是相对路径或者不是以C:\之类的字符串开头,则会失败。
  • 如果安装无法继续,则会生成MessageBox。您可以通过在语句末尾添加MessageBox来禁止/SD IDOK,但不会告知用户安装失败:我无法找到发送到stdout的方法来自NSIS。也许安装程序的返回代码足够了?
  • 如果磁盘可用空间非常低(如10kb),则安装程序根本不会运行;它没有空间将其临时DLL解压缩到\tmp目录。

此外,在我的下面的实现中,CheckFreeSpace在安装后具有空闲空间的硬编码值。显然可以参数化。

这是一个示例安装程序:

!include FileFunc.nsh
!insertmacro DriveSpace

Name "CheckFreeSpace"
OutFile "C:\CheckFreeSpace.exe"

InstallDir C:\tmp\checkfreespace

Page instfiles

Section "install_section" install_section_id
    Call CheckFreeSpace

    CreateDirectory $INSTDIR
    SetOutPath $INSTDIR
    File "C:\installme.bat"

    WriteUninstaller "$INSTDIR\Uninstall.exe"

    DetailPrint "Installation Successful."
SectionEnd

Section "Uninstall"

    RMDIR /r "$INSTDIR"

SectionEnd

Function CheckFreeSpace

    var /GLOBAL installsize
    var /GLOBAL adjustedinstallsize
    var /GLOBAL freespace
    var /GLOBAL instdrive

    ; Verify that we have sufficient space for the install

    ; SectionGetSize returns the size of each section in kilobyte.
    SectionGetSize ${install_section_id} $installsize

    ; Adjust the required install size by 10mb, as a minimum amount
    ; of free space left after installation.
    IntOp $adjustedinstallsize $installsize + 10240

    ; Compute the drive that is the installation target; the
    ; ${DriveSpace} macro will not accept a path, it must be a drive.
    StrCpy $instdrive $INSTDIR 3

    ; Compute drive space free in kilobyte
    ${DriveSpace} $instdrive "/D=F /S=K" $freespace

    DetailPrint "Determined installer needs $adjustedinstallsize kb ($installsize kb) while $freespace kb is free"

    IntCmp $adjustedinstallsize $freespace spaceok spaceok

    MessageBox MB_OK|MB_ICONSTOP "Insufficient space for installation. Please free space for installation directory $INSTDIR and try again."
    DetailPrint "Insufficient space for installation. Installer needs $adjustedinstallsize kb, but freespace is only $freespace kb."
    Abort "Insufficient space for installation."

  spaceok:
    DetailPrint "Installation target space is sufficient"

FunctionEnd

答案 2 :(得分:0)

您是否有静默安装的示例脚本?