User:Bnicer: Difference between revisions

From NSIS Wiki
Jump to navigationJump to search
No edit summary
(NSIS and I)
 
(9 intermediate revisions by 2 users not shown)
Line 1: Line 1:
<span style="color: red; font-size: 130%"><b>Get Size On Disk</b></span>
My current NSIS-related activities include testing, testing and more testing ...
 
There are two types of sizes. The physical size of files in bytes vs. the logical size on disk used.
This NSIS example code shows you how to get both sizes all in one go.
<highlight-nsis>
<highlight-nsis>
; A utility for computing the NSIS (or NSIS Unicode) 32-bit install folder size and the
ExecWait '"$UNINSTSTR" /U _?=$UNINST\bin'
; size of the uninstaller
; nsissize.nsi
; Compile & run the .exe
 
; Note: where either the folder or the uninstaller have been compressed, size on disk
; results will not be shown, as they would be incorrect
 
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 ZIP
Var ZIP_UN
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
  ${GetFileAttributes} "$NSIS" "COMPRESSED" $ZIP
  ${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
  ${GetFileAttributes} "$NSIS\uninst-nsis.exe" "COMPRESSED" $ZIP_UN
  ${GetSizeOnDisk} "$NSIS" "/M=uninst-nsis.exe /S=0B" "" $0 $1 $2
  Math::Script "r6 = ff($0 / 1024.0, 16 +1); \
  a = $0; b = $BLOCK; c = a % b; #[c == 0, c = $BLOCK]; r7 = (b - c + a); \
  r8 = ff(r7 / 1024.0, 16 +1)"
  StrCpy $SIZE_UN_B $0
  StrCpy $SIZE_UN_K $6
  StrCpy $SOD_UN_B $7
  StrCpy $SOD_UN_K $8
  ; 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)"
  StrCmp $ZIP "1" +3
  StrCmp $ZIP_UN "1" +2
  DetailPrint "SOD: $SOD_M MB ($SOD_B bytes)"
  DetailPrint ""
  DetailPrint "Uninstaller"
  DetailPrint "Size: $SIZE_UN_K KB ($SIZE_UN_B bytes)"
  StrCmp $ZIP "1" +3
  StrCmp $ZIP_UN "1" +2
  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
</highlight-nsis>
</highlight-nsis>
You should copy the next code into a separate file called <b>macros.nsh</b>.
<highlight-nsis>
; Macros include file
;--------------------------------
/*
FileFunction=[GetSizeOnDisk|GetClusterSize|GetFileAttributes]
*/
;_____________________________________________________________________________
;
;                        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
!macro GetFileAttributesCall _PATH _ATTR _RESULT
!verbose push
!verbose ${_FILEFUNC_VERBOSE}
Push `${_PATH}`
Push `${_ATTR}`
${CallArtificialFunction} GetFileAttributes_
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 (4KB clusters), if used, or size in bytes, if left empty ""
; Caution: All writable variables go on the stack; make sure you save them before
!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
FileOpen $9 '$R8\$R7' r
IfErrors +3
FileSeek $9 0 END $R6
FileClose $9
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 "" +10 0
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
; 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
; ---------------
; GetFileAttributes (FileFunc.nsh)
!define GetFileAttributes `!insertmacro GetFileAttributesCall`
!define un.GetFileAttributes `!insertmacro GetFileAttributesCall`
!macro GetFileAttributes
!macroend
!macro un.GetFileAttributes
!macroend
!macro GetFileAttributes_
!verbose push
!verbose ${_FILEFUNC_VERBOSE}
Exch $1
Exch
Exch $0
Exch
Push $2
Push $3
Push $4
Push $5
System::Call 'kernel32::GetFileAttributes(t r0)i .r2'
StrCmp $2 -1 FileFunc_GetFileAttributes_error
StrCpy $3 ''
IntOp $0 $2 & 0x4000
IntCmp $0 0 +2
StrCpy $3 'ENCRYPTED|'
IntOp $0 $2 & 0x2000
IntCmp $0 0 +2
StrCpy $3 'NOT_CONTENT_INDEXED|$3'
IntOp $0 $2 & 0x1000
IntCmp $0 0 +2
StrCpy $3 'OFFLINE|$3'
IntOp $0 $2 & 0x0800
IntCmp $0 0 +2
StrCpy $3 'COMPRESSED|$3'
IntOp $0 $2 & 0x0400
IntCmp $0 0 +2
StrCpy $3 'REPARSE_POINT|$3'
IntOp $0 $2 & 0x0200
IntCmp $0 0 +2
StrCpy $3 'SPARSE_FILE|$3'
IntOp $0 $2 & 0x0100
IntCmp $0 0 +2
StrCpy $3 'TEMPORARY|$3'
IntOp $0 $2 & 0x0080
IntCmp $0 0 +2
StrCpy $3 'NORMAL|$3'
IntOp $0 $2 & 0x0040
IntCmp $0 0 +2
StrCpy $3 'DEVICE|$3'
IntOp $0 $2 & 0x0020
IntCmp $0 0 +2
StrCpy $3 'ARCHIVE|$3'
IntOp $0 $2 & 0x0010
IntCmp $0 0 +2
StrCpy $3 'DIRECTORY|$3'
IntOp $0 $2 & 0x0004
IntCmp $0 0 +2
StrCpy $3 'SYSTEM|$3'
IntOp $0 $2 & 0x0002
IntCmp $0 0 +2
StrCpy $3 'HIDDEN|$3'
IntOp $0 $2 & 0x0001
IntCmp $0 0 +2
StrCpy $3 'READONLY|$3'
StrCpy $0 $3 -1
StrCmp $1 '' FileFunc_GetFileAttributes_end
StrCmp $1 'ALL' FileFunc_GetFileAttributes_end
FileFunc_GetFileAttributes_attrcmp:
StrCpy $5 0
IntOp $5 $5 + 1
StrCpy $4 $1 1 $5
StrCmp $4 '' +2
StrCmp $4 '|'  0 -3
StrCpy $2 $1 $5
IntOp $5 $5 + 1
StrCpy $1 $1 '' $5
StrLen $3 $2
StrCpy $5 -1
IntOp $5 $5 + 1
StrCpy $4 $0 $3 $5
StrCmp $4 '' FileFunc_GetFileAttributes_notfound
StrCmp $4 $2 0 -3
StrCmp $1 '' 0 FileFunc_GetFileAttributes_attrcmp
StrCpy $0 1
goto FileFunc_GetFileAttributes_end
FileFunc_GetFileAttributes_notfound:
StrCpy $0 0
goto FileFunc_GetFileAttributes_end
FileFunc_GetFileAttributes_error:
SetErrors
StrCpy $0 ''
FileFunc_GetFileAttributes_end:
Pop $5
Pop $4
Pop $3
Pop $2
Pop $1
Exch $0
!verbose pop
!macroend
!define GetFileVersion `!insertmacro GetFileVersionCall`
!define un.GetFileVersion `!insertmacro GetFileVersionCall`
!macro GetFileVersion
!macroend
!macro un.GetFileVersion
!macroend
!macro GetFileVersion_
!verbose push
!verbose ${_FILEFUNC_VERBOSE}
Exch $0
Push $1
Push $2
Push $3
Push $4
Push $5
Push $6
ClearErrors
GetDllVersion '$0' $1 $2
IfErrors FileFunc_GetFileVersion_error
IntOp $3 $1 >> 16
IntOp $3 $3 & 0x0000FFFF
IntOp $4 $1 & 0x0000FFFF
IntOp $5 $2 >> 16
IntOp $5 $5 & 0x0000FFFF
IntOp $6 $2 & 0x0000FFFF
StrCpy $0 '$3.$4.$5.$6'
goto FileFunc_GetFileVersion_end
FileFunc_GetFileVersion_error:
SetErrors
StrCpy $0 ''
FileFunc_GetFileVersion_end:
Pop $6
Pop $5
Pop $4
Pop $3
Pop $2
Pop $1
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
</highlight-nsis>
<span style="font-size: 110%"><b>Credits:</b></span>
<em>GetFileAttributes</em> is borrowed from <b>filefunc.nsh</b>. For usage documentation look under section E.1.7 in the Users Manual.
<em>GetSizeOnDisk</em> also comes from <b>filefunc.nsh</b>, but has been altered slightly and renamed. The original macro was called <em>GetSize</em>. You will find it in the Users Manual under E.1.3.

Latest revision as of 01:14, 16 March 2013

My current NSIS-related activities include testing, testing and more testing ...

ExecWait '"$UNINSTSTR" /U _?=$UNINST\bin'