Get size on disk: Difference between revisions

From NSIS Wiki
Jump to navigationJump to search
(Size On Disk (SOD) utility to get the space used by directories and files)
(Size On Disk (SOD) utility)
Line 381: Line 381:
IntOp $R4 $R4 + 1
IntOp $R4 $R4 + 1
goto FileFunc_GetSize_findnext
goto FileFunc_GetSize_findnext
; insert code
StrCmp $R1 "" FileFunc_GetSize_fileopen
StrCpy $R0 0
System::Call 'kernel32::GetFileAttributes(t "$R8\$R7")i .R2'
StrCmp $R2 -1 FileFunc_GetSize_fileopen
IntOp $R0 $R2 & 0x0800
IntCmp $R0 0 0 0 +3
IntOp $R0 $R2 & 0x0200
IntCmp $R0 0 FileFunc_GetSize_fileopen
System::Call 'kernel32::GetCompressedFileSize(t "$R8\$R7", i)i .R6'
IntCmp $R6 4096 +2 0 +2
StrCpy $R6 4096
goto FileFunc_GetSize_fileclose
FileFunc_GetSize_fileopen:
; end insert
FileOpen $9 '$R8\$R7' r
FileOpen $9 '$R8\$R7' r
IfErrors +3
IfErrors +3
FileSeek $9 0 END $R6
FileSeek $9 0 END $R6
FileClose $9
FileClose $9
; insert code
FileFunc_GetSize_fileclose:
; end insert
StrCmp $5 '' +2
StrCmp $5 '' +2
IntCmp $R6 $5 0 FileFunc_GetSize_findnext
IntCmp $R6 $5 0 FileFunc_GetSize_findnext
Line 392: Line 410:
; insert code
; insert code
StrCmp $R1 "" FileFunc_GetSize_file_add
StrCmp $R1 "" FileFunc_GetSize_file_add
System::Call 'kernel32::GetFileAttributes(t "$R8\$R7")i .R2'
StrCmp $R0 0 0 FileFunc_GetSize_file_add
StrCmp $R2 -1 FileFunc_GetSize_file_logical
IntOp $R0 $R2 & 0x0800
IntCmp $R0 0 0 0 +3
IntOp $R0 $R2 & 0x0200
IntCmp $R0 0 FileFunc_GetSize_file_logical
System::Call 'kernel32::GetCompressedFileSize(t "$R8\$R7", i)i .R6'
IntCmp $R6 4096 FileFunc_GetSize_file_add 0 FileFunc_GetSize_file_add
StrCpy $R6 4096
goto FileFunc_GetSize_file_add
FileFunc_GetSize_file_logical:
StrCpy $R0 $R1
StrCpy $R0 $R1
IntOp $R6 $R6 + $R0
IntOp $R6 $R6 + $R0

Revision as of 08:46, 13 February 2013

Author: Bnicer (talk, contrib)


This example code shows you how to get the space used by directories and files.

; A utility for computing the NSIS (or NSIS Unicode) install folder size and the size of
; the uninstaller
; nsissize.nsi
; Compile & run the .exe
 
Name "SOD Tool"
RequestExecutionLevel user
!define LOCAL "" ; Path where local include files reside
OutFile "${LOCAL}nsissize.exe"
!include "${LOCAL}macros.nsh"
ReserveFile "${NSISDIR}\Plugins\Math.dll"
Icon "${LOCAL}arrows.ico"
ShowInstDetails show
 
; Variables
Var NSIS
Var COUNT
Var BLOCK
Var FILES
Var FOLDERS
Var SIZE_B
Var SIZE_M
Var SOD_B
Var SOD_K
Var SOD_M
Var SIZE_UN_B
Var SIZE_UN_K
Var SOD_UN_B
Var SOD_UN_K
 
Function Separator ; comma
  StrCpy $R2 $R1
  StrCpy $COUNT "16" ; 1,000,000,000,000,000 limit
  StrLen $R4 $R1
  loop:
  IntCmp $COUNT 3 endloop endloop 0
  IntCmp $R4 $COUNT 0 +7 0
  IntOp $COUNT $COUNT - 1
  StrCpy $R2 $R2 -$COUNT
  StrCpy $R3 $R1 "" -$COUNT
  StrCpy $R2 "$R2,$R3"
  IntOp $COUNT $COUNT - 2
  Goto loop
  IntOp $COUNT $COUNT - 3
  Goto loop
  endloop:
FunctionEnd
 
Section
; root
  ReadRegStr $NSIS HKLM "SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\\
  NSIS Unicode" "InstallLocation"
  IfErrors 0 begin
  ClearErrors
  ReadRegStr $NSIS HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\\
  NSIS Unicode" "InstallLocation"
  IfErrors 0 begin
  ClearErrors
  ReadRegStr $NSIS HKLM "SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\\
  NSIS ANSI" "InstallLocation"
  IfErrors 0 begin
  ClearErrors
  ReadRegStr $NSIS HKLM "SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\\
  NSIS" "InstallLocation"
  IfErrors 0 begin
  ClearErrors
  ReadRegStr $NSIS HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\\
  NSIS ANSI" "InstallLocation"
  IfErrors 0 begin
  ClearErrors
  ReadRegStr $NSIS HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\\
  NSIS" "InstallLocation"
  IfErrors 0 begin
  ClearErrors
  Goto done
  begin:
  IfFileExists "$NSIS" 0 done
  ${GetClusterSize} $BLOCK
  ${GetSizeOnDisk} "$NSIS" "/S=0B" "" $0 $1 $2
  Math::Script "r3 = ff($0 / 1024 / 1024.0, 16 +2"
  StrCpy $SIZE_B $0
  StrCpy $FILES $1
  StrCpy $FOLDERS $2
  StrCpy $SIZE_M $3
  ${GetSizeOnDisk} "$NSIS" "/S=0B" "$BLOCK" $0 $1 $2
  Math::Script "r4 = ff($0 / 1024.0, 16 +0); r5 = ff(r4 / 1024.0, 16 +2)"
  StrCpy $SOD_B $0
  StrCpy $SOD_K $4
  StrCpy $SOD_M $5
; uninstaller
  IfFileExists "$NSIS\uninst-nsis.exe" 0 done
  ${GetSizeOnDisk} "$NSIS" "/M=uninst-nsis.exe /S=0B" "" $0 $1 $2
  Math::Script "r6 = ff($0 / 1024.0, 16 +1)"
  StrCpy $SIZE_UN_B $0
  StrCpy $SIZE_UN_K $6
  ${GetSizeOnDisk} "$NSIS" "/M=uninst-nsis.exe /S=0B" "$BLOCK" $0 $1 $2
  Math::Script "r7 = ff($0 / 1024.0, 16 +1)"
  StrCpy $SOD_UN_B $0
  StrCpy $SOD_UN_K $7
; format
  StrCpy $R1 $SIZE_B
  Call Separator
  StrCpy $SIZE_B $R2
 
  StrCpy $R1 $SOD_B
  Call Separator
  StrCpy $SOD_B $R2
 
  StrCpy $R1 $SOD_K
  Call Separator
  StrCpy $SOD_K $R2
 
  StrCpy $R1 $SIZE_UN_B
  Call Separator
  StrCpy $SIZE_UN_B $R2
  StrCpy $R1 $SOD_UN_B
  Call Separator
  StrCpy $SOD_UN_B $R2
; output
  DetailPrint ""
  DetailPrint "$NSIS"
  DetailPrint "Size: $SIZE_M MB ($SIZE_B bytes)"
  DetailPrint "SOD: $SOD_M MB ($SOD_B bytes)"
  DetailPrint ""
  DetailPrint "Uninstaller"
  DetailPrint "Size: $SIZE_UN_K KB ($SIZE_UN_B bytes)"
  DetailPrint "SOD: $SOD_UN_K KB ($SOD_UN_B bytes)"
  DetailPrint ""
  DetailPrint "$FILES files $FOLDERS folders $SOD_K Kb"
  DetailPrint ""
  Goto completed
  done:
  DetailPrint "File not found."
  completed:
SectionEnd
 
;--------------------------------
# EOF

You should copy the next code into a separate file: macros.nsh.

; Macros include (TN)
;--------------------------------
/*
 
 FileFunction=[GetSizeOnDisk|GetClusterSize]
 
*/
;_____________________________________________________________________________
;
;                         Macros
;_____________________________________________________________________________
;
; Change log window verbosity (default: 3=no script)
;
; Example:
; !include "sizemacros.nsh"
; !insertmacro GetSizeOnDisk
; ${FILEFUNC_VERBOSE} 4   # all verbosity
; !insertmacro GetClusterSize
; ${FILEFUNC_VERBOSE} 3   # no script
 
!include Util.nsh ; for "CallArtificialFunction"
 
!verbose push
!verbose 3
!ifndef _FILEFUNC_VERBOSE
	!define _FILEFUNC_VERBOSE 3
!endif
!verbose ${_FILEFUNC_VERBOSE}
!define FILEFUNC_VERBOSE `!insertmacro FILEFUNC_VERBOSE`
!verbose pop
 
!macro FILEFUNC_VERBOSE _VERBOSE
	!verbose push
	!verbose 3
	!undef _FILEFUNC_VERBOSE
	!define _FILEFUNC_VERBOSE ${_VERBOSE}
	!verbose pop
!macroend
 
!macro GetSizeOnDiskCall _PATH _OPTIONS _FILESYSTEM _RESULT1 _RESULT2 _RESULT3
	!verbose push
	!verbose ${_FILEFUNC_VERBOSE}
	Push `${_PATH}`
	Push `${_OPTIONS}`
	Push `${_FILESYSTEM}` ; block size
	${CallArtificialFunction} GetSizeOnDisk_
	Pop ${_RESULT1}
	Pop ${_RESULT2}
	Pop ${_RESULT3}
	!verbose pop
!macroend
 
!macro GetClusterSizeCall _RESULT
	!verbose push
	!verbose ${_FILEFUNC_VERBOSE}
	${CallArtificialFunction} GetClusterSize_
	Pop ${_RESULT}
	!verbose pop
!macroend
 
; ---------------
; GetSizeOnDisk (modified "GetSize" - FileFunc.nsh - KiCHiK - Function "FindFiles")
 
!define GetSizeOnDisk `!insertmacro GetSizeOnDiskCall`
!define un.GetSizeOnDisk `!insertmacro GetSizeOnDiskCall`
 
!macro GetSizeOnDisk
!macroend
 
!macro un.GetSizeOnDisk
!macroend
 
; Usage: similar to "GetSize"
 
; For documentation, see the NSIS user manual: E.1.3 GetSize
; Three values are returned
 
; $var1		; Result1: Size/Size on disk
; $var2		; Result2: Sum of files
; $var3		; Result3: Sum of directories
 
; Example: ${GetSizeOnDisk} "$INSTDIR" "/S=0K" "4096" $0 $1 $2
 
; Specifying 4096 (logical size) toggles the result
; Output is size on disk, if used, or size in bytes, if left empty ""
 
!macro GetSizeOnDisk_
	!verbose push
	!verbose ${_FILEFUNC_VERBOSE}
 
	; replace
	Exch $R1
	Exch
	Exch $1
	Exch 2
	; end replace
	Exch $0
	Exch
	Push $2
	Push $3
	Push $4
	Push $5
	Push $6
	Push $7
	Push $8
	Push $9
	; insert code
	Push $R2
	; end insert
	Push $R3
	Push $R4
	Push $R5
	Push $R6
	Push $R7
	Push $R8
	Push $R9
	ClearErrors
 
	StrCpy $R9 $0 1 -1
	StrCmp $R9 '\' 0 +3
	StrCpy $0 $0 -1
	goto -3
	IfFileExists '$0\*.*' 0 FileFunc_GetSize_error
 
	StrCpy $3 ''
	StrCpy $4 ''
	StrCpy $5 ''
	StrCpy $6 ''
	StrCpy $8 0
	StrCpy $R3 ''
	StrCpy $R4 ''
	StrCpy $R5 ''
 
	FileFunc_GetSize_option:
	StrCpy $R9 $1 1
	StrCpy $1 $1 '' 1
	StrCmp $R9 ' ' -2
	StrCmp $R9 '' FileFunc_GetSize_sizeset
	StrCmp $R9 '/' 0 -4
 
	StrCpy $9 -1
	IntOp $9 $9 + 1
	StrCpy $R9 $1 1 $9
	StrCmp $R9 '' +2
	StrCmp $R9 '/' 0 -3
	StrCpy $8 $1 $9
	StrCpy $8 $8 '' 2
	StrCpy $R9 $8 '' -1
	StrCmp $R9 ' ' 0 +3
	StrCpy $8 $8 -1
	goto -3
	StrCpy $R9 $1 2
	StrCpy $1 $1 '' $9
 
	StrCmp $R9 'M=' 0 FileFunc_GetSize_size
	StrCpy $4 $8
	goto FileFunc_GetSize_option
 
	FileFunc_GetSize_size:
	StrCmp $R9 'S=' 0 FileFunc_GetSize_gotosubdir
	StrCpy $6 $8
	goto FileFunc_GetSize_option
 
	FileFunc_GetSize_gotosubdir:
	StrCmp $R9 'G=' 0 FileFunc_GetSize_error
	StrCpy $7 $8
	StrCmp $7 '' +3
	StrCmp $7 '1' +2
	StrCmp $7 '0' 0 FileFunc_GetSize_error
	goto FileFunc_GetSize_option
 
	FileFunc_GetSize_sizeset:
	StrCmp $6 '' FileFunc_GetSize_default
	StrCpy $9 0
	StrCpy $R9 $6 1 $9
	StrCmp $R9 '' +4
	StrCmp $R9 ':' +3
	IntOp $9 $9 + 1
	goto -4
	StrCpy $5 $6 $9
	IntOp $9 $9 + 1
	StrCpy $1 $6 1 -1
	StrCpy $6 $6 -1 $9
	StrCmp $5 '' +2
	IntOp $5 $5 + 0
	StrCmp $6 '' +2
	IntOp $6 $6 + 0
 
	StrCmp $1 'B' 0 +4
	StrCpy $1 1
	StrCpy $2 bytes
	goto FileFunc_GetSize_default
	StrCmp $1 'K' 0 +4
	StrCpy $1 1024
	StrCpy $2 Kb
	goto FileFunc_GetSize_default
	StrCmp $1 'M' 0 +4
	StrCpy $1 1048576
	StrCpy $2 Mb
	goto FileFunc_GetSize_default
	StrCmp $1 'G' 0 FileFunc_GetSize_error
	StrCpy $1 1073741824
	StrCpy $2 Gb
 
	FileFunc_GetSize_default:
	StrCmp $4 '' 0 +2
	StrCpy $4 '*.*'
	StrCmp $7 '' 0 +2
	StrCpy $7 '1'
 
	StrCpy $8 1
	Push $0
	SetDetailsPrint textonly
 
	FileFunc_GetSize_nextdir:
	IntOp $8 $8 - 1
	Pop $R8
	FindFirst $0 $R7 '$R8\$4'
	IfErrors FileFunc_GetSize_show
	StrCmp $R7 '.' 0 FileFunc_GetSize_dir
	FindNext $0 $R7
	StrCmp $R7 '..' 0 FileFunc_GetSize_dir
	FindNext $0 $R7
	IfErrors 0 FileFunc_GetSize_dir
	FindClose $0
	goto FileFunc_GetSize_show
 
	FileFunc_GetSize_dir:
	IfFileExists '$R8\$R7\*.*' 0 FileFunc_GetSize_file
	IntOp $R5 $R5 + 1
	goto FileFunc_GetSize_findnext
 
	FileFunc_GetSize_file:
	StrCpy $R6 0
	StrCmp $5$6 '' 0 +3
	IntOp $R4 $R4 + 1
	goto FileFunc_GetSize_findnext
	; insert code
	StrCmp $R1 "" FileFunc_GetSize_fileopen
	StrCpy $R0 0
	System::Call 'kernel32::GetFileAttributes(t "$R8\$R7")i .R2'
	StrCmp $R2 -1 FileFunc_GetSize_fileopen
	IntOp $R0 $R2 & 0x0800
	IntCmp $R0 0 0 0 +3
	IntOp $R0 $R2 & 0x0200
	IntCmp $R0 0 FileFunc_GetSize_fileopen
	System::Call 'kernel32::GetCompressedFileSize(t "$R8\$R7", i)i .R6'
	IntCmp $R6 4096 +2 0 +2
	StrCpy $R6 4096
	goto FileFunc_GetSize_fileclose
	FileFunc_GetSize_fileopen:
	; end insert
	FileOpen $9 '$R8\$R7' r
	IfErrors +3
	FileSeek $9 0 END $R6
	FileClose $9
	; insert code
	FileFunc_GetSize_fileclose:
	; end insert
	StrCmp $5 '' +2
	IntCmp $R6 $5 0 FileFunc_GetSize_findnext
	StrCmp $6 '' +2
	IntCmp $R6 $6 0 0 FileFunc_GetSize_findnext
	IntOp $R4 $R4 + 1
	; insert code
	StrCmp $R1 "" FileFunc_GetSize_file_add
	StrCmp $R0 0 0 FileFunc_GetSize_file_add
	StrCpy $R0 $R1
	IntOp $R6 $R6 + $R0
	IntOp $R1 $R6 % $R0
	StrCmp $R1 0 0 +2
	StrCpy $R1 $R0
	IntOp $R2 $R0 - $R1
	IntOp $R6 $R6 - $R0
	IntOp $R6 $R6 + $R2
	StrCpy $R1 $R0
	FileFunc_GetSize_file_add:
	; end insert
	System::Int64Op $R3 + $R6
	Pop $R3
 
	FileFunc_GetSize_findnext:
	FindNext $0 $R7
	IfErrors 0 FileFunc_GetSize_dir
	FindClose $0
 
	FileFunc_GetSize_show:
	StrCmp $5$6 '' FileFunc_GetSize_nosize
	System::Int64Op $R3 / $1
	Pop $9
	DetailPrint 'Size:$9 $2  Files:$R4  Folders:$R5'
	goto FileFunc_GetSize_subdir
	FileFunc_GetSize_nosize:
	DetailPrint 'Files:$R4  Folders:$R5'
 
	FileFunc_GetSize_subdir:
	StrCmp $7 0 FileFunc_GetSize_preend
	FindFirst $0 $R7 '$R8\*.*'
	StrCmp $R7 '.' 0 FileFunc_GetSize_pushdir
	FindNext $0 $R7
	StrCmp $R7 '..' 0 FileFunc_GetSize_pushdir
	FindNext $0 $R7
	IfErrors 0 FileFunc_GetSize_pushdir
	FindClose $0
	StrCmp $8 0 FileFunc_GetSize_preend FileFunc_GetSize_nextdir
 
	FileFunc_GetSize_pushdir:
	IfFileExists '$R8\$R7\*.*' 0 +3
	Push '$R8\$R7'
	IntOp $8 $8 + 1
	FindNext $0 $R7
	IfErrors 0 FileFunc_GetSize_pushdir
	FindClose $0
	StrCmp $8 0 FileFunc_GetSize_preend FileFunc_GetSize_nextdir
 
	FileFunc_GetSize_preend:
	StrCmp $R3 '' FileFunc_GetSize_nosizeend
	System::Int64Op $R3 / $1
	Pop $R3
	FileFunc_GetSize_nosizeend:
	StrCpy $2 $R4
	StrCpy $1 $R5
	StrCpy $0 $R3
	goto FileFunc_GetSize_end
 
	FileFunc_GetSize_error:
	SetErrors
	StrCpy $0 ''
	StrCpy $1 ''
	StrCpy $2 ''
 
	FileFunc_GetSize_end:
	SetDetailsPrint both
	Pop $R9
	Pop $R8
	Pop $R7
	Pop $R6
	Pop $R5
	Pop $R4
	Pop $R3
	; insert code
	Pop $R2
	; end insert
	Pop $9
	Pop $8
	Pop $7
	Pop $6
	Pop $5
	Pop $4
	Pop $3
	Exch $2
	Exch
	Exch $1
	Exch 2
	Exch $0
 
	!verbose pop
!macroend
 
; ---------------
; GetClusterSize
 
!define GetClusterSize `!insertmacro GetClusterSizeCall`
!define un.GetClusterSize `!insertmacro GetClusterSizeCall`
 
!macro GetClusterSize
!macroend
 
!macro un.GetClusterSize
!macroend
 
!macro GetClusterSize_
	!verbose push
	!verbose ${_FILEFUNC_VERBOSE}
 
	System::Call 'kernel32::GetDiskFreeSpace(i0,*i0r0,*i0r1,*i0r2,*i)'
	IntOp $0 $0 * $1
	Push $0
 
	!verbose pop
!macroend

Credits:

GetSizeOnDisk has been altered slightly and renamed. The original macro is called GetSize. You will find it in the Users Manual under E.1.3.