Come posso controllare lo spazio libero nel corso di una installazione non presidiata NullSoft?

StackOverflow https://stackoverflow.com/questions/989172

Domanda

In modalità di installazione silenziosa l'utente non viene chiesto il bersaglio di installazione con il PageEx directory , e quindi le funzioni DirVerify e noreferrer GetInstDirError non vengono mai chiamati.

Questo è applicabile anche alle installazioni che hardcode l'obiettivo di installazione (una cattiva idea) per lo stesso motivo di cui sopra:. La PageEx directory non è mai invocato

È stato utile?

Soluzione

Il codice di esempio è ok, ma $ chiamando {} DriveSpace su Win9x potrebbe fallire. Ho anche rimosso la necessità di specificare la sezione 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

Ho fatto solo limitato di test, speriamo che non ci sono bug:)

Altri suggerimenti

ho scritto una funzione chiamata CheckFreeSpace in NSIS per fare questo. Purtroppo ha le seguenti limitazioni:

  • Per calcolare le dimensioni di tutte le sezioni in vostra installazione, è necessario modificare CheckFreeSpace per aggiungere ogni sezione, conoscendo ogni variabile che ogni id sezione è stata scritta in. Non riesco a trovare un modo di iterare su tutte le sezioni che verranno installati utilizzando NSIS.
  • unità di installazione deve essere calcolato perché ${DriveSpace} richiede una lettera di unità, non un percorso a una directory arbitraria. La stringa lettera dell'unità viene calcolata con StrCpy $instdrive $INSTDIR 3. Se la variabile $INSTDIR è un percorso relativo o non inizia con una stringa come C:\, questo sarà sicuro.
  • Se l'installazione non può continuare produce un MessageBox. È possibile sopprimere la MessageBox aggiungendo /SD IDOK alla fine della dichiarazione, ma poi l'utente non viene informato del fallimento di installazione: non riesco a trovare un modo per emettere a stdout da NSIS. Forse il codice di ritorno dal programma di installazione è sufficiente?
  • Se lo spazio libero su disco è davvero basso (come 10kb), il programma di installazione non funzionerà affatto; non ha spazio per disfare la sua temporanea DLL nella directory \tmp.

Inoltre, nella mia implementazione di seguito, CheckFreeSpace ha un valore hardcoded per lo spazio libero dopo l'installazione. Ovviamente che possono essere parametrizzate.

Qui è all'interno di un programma di installazione di esempio:

!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

Hai uno script di esempio per l'installazione silenziosa?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top