如何在 NullSoft 静默安装过程中检查可用空间?

发布于 2024-07-24 04:24:29 字数 481 浏览 11 评论 0原文

在静默安装模式下,不会使用 询问用户安装目标PageEx 目录,因此函数 DirVerifyGetInstDirError 从未被调用。

这也适用于出于与上述相同的原因对安装目标进行硬编码的安装(一个坏主意):永远不会调用 PageEx 目录

In silent install mode the user is not asked about the installation target with the PageEx directory, and therefore the functions DirVerify and GetInstDirError are never called.

This is also applicable to installs that hardcode the installation target (a bad idea) for the same reason as above: the PageEx directory is never invoked.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

撩起发的微风 2024-07-31 04:24:29

您的示例代码没问题,但在 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

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

Your sample code is ok, but calling ${DriveSpace} on Win9x could fail. I also removed the need to specify the section id's

!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

I only did limited testing, hopefully there are no bugs :)

蘑菇王子 2024-07-31 04:24:29

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

  • 要计算安装中所有部分的大小,您必须通过了解每个部分 id 写入的每个变量来修改 CheckFreeSpace 以添加每个部分。 我找不到迭代将使用 NSIS 安装的所有部分的方法。
  • 必须计算安装驱动器,因为 ${DriveSpace} 需要驱动器号,而不是任意目录的路径。 驱动器号字符串使用 StrCpy $instdrive $INSTDIR 3 计算。 如果 $INSTDIR 变量是相对路径或不以 C:\ 等字符串开头,则此操作将会失败。
  • 如果安装无法继续,它会生成一个 MessageBox。 您可以通过在语句末尾添加 /SD IDOK 来抑制 MessageBox,但随后用户不会收到安装失败的通知:我找不到方法从 NSIS 发送到 stdout。 也许安装程序的返回代码就足够了?
  • 如果磁盘可用空间非常低(例如 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

I wrote a function called CheckFreeSpace in NSIS to do this. Unfortunately it has the following limitations:

  • To compute the size of all the sections in your installation, you have to modify CheckFreeSpace to add each section, by knowing each variable that each section id was written into. I can't find a way of iterating over all sections that will be installed using NSIS.
  • Installation drive must be computed because ${DriveSpace} requires a drive letter, not a path to an arbitrary directory. The drive letter string is computed with StrCpy $instdrive $INSTDIR 3. If the $INSTDIR variable is a relative path or does not begin with a string such as C:\, this will fail.
  • If the installation cannot continue it produces a MessageBox. You can suppress the MessageBox by adding /SD IDOK at the end of the statement, but then the user is not informed of the installation failure: I can't find a way to emit to stdout from NSIS. Perhaps the return code from the installer is enough?
  • If the disk free space is really low (like 10kb), the installer won't run at all; it doesn't have space to unpack its temporary DLL's into the \tmp directory.

Also, in my implementation below, CheckFreeSpace has a hardcoded value for the space free after installation. Obviously that can be parameterized.

Here it is within a sample installer:

!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
酒与心事 2024-07-31 04:24:29

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

Do you have a sample script for silent install?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文