Comment puis-je vérifier l'espace libre au cours d'un silencieux NullSoft installer?
Question
En mode d'installation silencieuse l'utilisateur n'a pas posé des questions sur la cible d'installation avec le PageEx directory
, et donc les fonctions DirVerify
et noreferrer de GetInstDirError
ne sont jamais appelés.
Il est également applicable aux installations qui hardcode la cible d'installation (une mauvaise idée) pour la même raison que ci-dessus. PageEx directory
l'est jamais invoqué
La solution
Votre exemple de code est ok, mais appelant $ {} DriveSpace sur Win9x pourrait échouer. J'ai aussi enlevé la nécessité de préciser la section 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
Je ne l'ai fait des essais limités, nous l'espérons, il n'y a pas de bugs:)
Autres conseils
J'ai écrit une fonction appelée CheckFreeSpace
dans NSIS pour ce faire. Malheureusement, il a les limitations suivantes:
- Pour calculer la taille de toutes les sections de votre installation, vous devez modifier
CheckFreeSpace
pour ajouter chaque section, en connaissant chaque variable qui a été écrit chaque identifiant de section dans. Je ne peux pas trouver un moyen de itérer sur toutes les sections qui seront installées à l'aide NSIS. - Le lecteur d'installation doit être calculée, car
${DriveSpace}
exige une lettre de lecteur, pas un chemin vers un répertoire arbitraire. La chaîne de lettre de lecteur est calculée avecStrCpy $instdrive $INSTDIR 3
. Si la variable$INSTDIR
est un chemin relatif ou ne commence pas par une chaîne telle queC:\
, ce échouera. - Si l'installation ne peut pas continuer produit un
MessageBox
. Vous pouvez supprimer laMessageBox
en ajoutant/SD IDOK
à la fin de l'instruction, mais l'utilisateur n'a pas informé de l'échec de l'installation: Je ne peux pas trouver un moyen d'émettre àstdout
de NSIS. Peut-être le code de retour de l'installateur est suffisant? - Si l'espace disque libre est très faible (comme 10kb), le programme d'installation ne fonctionnera pas du tout; il ne dispose pas d'espace pour déballer sa DLL temporaire de dans le répertoire
\tmp
.
En outre, dans ma mise en œuvre ci-dessous, CheckFreeSpace
a une valeur spécifique de l'espace libre après l'installation. Il est évident que cela peut être paramétrés.
Ici, il est dans un installateur exemple:
!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
Avez-vous un exemple de script pour une installation silencieuse?