Archive: [Solution] Getting file size at compile time


[Solution] Getting file size at compile time
Hi guys.

I managed to solve my previous issue, here's the code I came up with to get a size of file at compile time:

!macro CTFileSize _FILE _RESULT

!echo 'CTFileSize: "${_FILE}"'

!verbose push
!verbose 3

!tempfile __TEMP_BAT_FILE
!delfile "${__TEMP_BAT_FILE}"
!tempfile __TEMP_NSH_FILE
!delfile "${__TEMP_NSH_FILE}"

!system 'cmd /C ECHO @ECHO Push %~z1 > "${__TEMP_BAT_FILE}.bat"'
!system '"${__TEMP_BAT_FILE}.bat" "${_FILE}" > "${__TEMP_NSH_FILE}.nsh"'
!include "${__TEMP_NSH_FILE}.nsh"

!delfile "${__TEMP_BAT_FILE}.bat"
!undef __TEMP_BAT_FILE
!delfile "${__TEMP_NSH_FILE}.nsh"
!undef __TEMP_NSH_FILE

Pop ${_RESULT}

!verbose pop

!macroend


Usage:

!insertmacro CTFileSize "C:\Windows\notepad.exe" $R0
MessageBox MB_OK "Size of notepad: $R0 bytes"


Perhaps somebody else will find it useful.

P.S. I use this code to calculate the size of a section for several install modes, and change it at runtime, using the SectionSetSize function.
The docs say:
"The Value for Size must be entered in KiloByte and supports only whole numbers."
Only whole KBs? Why the heck is that? o_0

Whole KBs is probably to allow larger sizes within a 32 bits variable.

Next time, please post the solution in the thread where you asked the question.


Why post a new thread?

My take on this:

!macro GetFileSize define file
!tempfile __GetFileSize
!execute 'cmd /E:ON /V:OFF /C if 1==1 for %A in ("${file}") do echo !define ${define} "%~zA" > "${__GetFileSize}"'
!include "${__GetFileSize}"
!delfile "${__GetFileSize}"
!undef __GetFileSize
!macroend

!insertmacro GetFileSize thesize "$%windir%\explorer.exe"
!echo thesize=${thesize}
Edit: Added missing !undef

Next time, please post the solution in the thread where you asked the question.
OK, sorry, I just thought that it would be easier for others to find it that way. (SEO, page title, etc.)
Also, maybe it's worth to add this to the wiki?

Whole KBs is probably to allow larger sizes within a 32 bits variable.
More than 4 GB for an installer?
I don't think so (I bet it won't work anyway).
If you know another way of e.g. setting a section size in bytes and not in KBs, tell me. It's not a must but it looks nicer. After all, NSIS does that by default.

My take on this
Wow, nice! :)
I'm not too good at working with cmd, so I would never come up with this.
A couple of corrections, though:
* A "/Q" parameter for cmd to turn off echo.
* What is the "if 1==1" for? I guess nothing.
* You forgot to undef __GetFileSize.

Also, it's more convenient for me to get the size to a variable, and not to a define, so here's my version:
!macro CTFileSize _FILE _RESULT
!tempfile __TEMP_NSH_FILE
!execute 'cmd /Q /E:ON /V:OFF /C for %A in ("${_FILE}") do echo StrCpy ${_RESULT} %~zA > "${__TEMP_NSH_FILE}"'
!include "${__TEMP_NSH_FILE}"
!delfile "${__TEMP_NSH_FILE}"
!undef __TEMP_NSH_FILE
!macroend
Usage is the same as in the first post:
!insertmacro CTFileSize "C:\Windows\notepad.exe" $R0
MessageBox MB_OK "Size of notepad: $R0 bytes"

IF 1==1 does "nothing" yes, but it fixes bugs in cmd.exe


That's interesting, what bugs does it fix?


Originally posted by stopasking
More than 4 GB for an installer?
I don't think so (I bet it won't work anyway).
I have one. CopyFiles and AddSize are your friends.

I need to get a size of a folder at compile time.
I came up with the following batch script:

@ECHO OFF
SET sum=0
FOR /R %1 %%A IN (*) DO ( SET /A sum+=%%~zA )
echo %sum%
It works.
Now I want to use it as a command line parameter of cmd.
I tried the following:
cmd /Q /E:ON /V:OFF /K SET sum=0 & FOR /R "%userprofile%\Desktop\" %A IN (*) DO ( SET /A sum+=%~zA ) & ECHO %sum%
but it doesn't work as expected.

Help me please.

--EDIT--

That's what I came up with:
!macro CTFolderSize _FOLDER _RESULT
!tempfile __TEMP_NSH_FILE
!execute 'cmd /Q /E:ON /V:OFF /C (SET sum=0) & (FOR /R "${_FOLDER}" %A IN (*) DO SET /A "sum+=%~zA" > NUL ) & ( CALL ECHO StrCpy ${_RESULT} %sum% > "${__TEMP_NSH_FILE}" )'
!include "${__TEMP_NSH_FILE}"
!delfile "${__TEMP_NSH_FILE}"
!undef __TEMP_NSH_FILE
!macroend
I'm not sure how good is the solution, but it seems to work.