Old 5th March 2007, 10:17   #1
bnicer
Senior Member
 
Join Date: Feb 2005
Location: London
Posts: 218
Add or Remove Programs - Size missing

Hi all,

I seem to have lost the Size attribute in the Add or Remove Programs list (XP).

The projected install size still appears in the setup (in the directory page).

I've tried removing the SectionSetSize calls to see if that might be causing it, but the size still won't show up in Add or Remove Programs. I know it should, but I don't know if it's something I did or a bug. Probably the former.

Where else can you save/store the size in a *.nsi script?

Using or not using AddSize also isn't responsible.

Many programs don't have a size in Add or Remove, and I don't consider it very important. Just puzzling...
bnicer is offline   Reply With Quote
Old 5th March 2007, 13:34   #2
kichik
M.I.A.
[NSIS Dev, Mod]
 
kichik's Avatar
 
Join Date: Oct 2001
Location: Israel
Posts: 11,343
AddSize or SectionSetSize have nothing to do with the Add/Remove Control Panel. Raymond Chen had a blog entry about the size attribute in there. It should shed some light on what's happening there. To sum it up, you should write the number of KBs into EstimatedSize in your uninstall key in the registry.

NSIS FAQ | NSIS Home Page | Donate $
"I hear and I forget. I see and I remember. I do and I understand." -- Confucius
kichik is offline   Reply With Quote
Old 5th March 2007, 20:52   #3
bnicer
Senior Member
 
Join Date: Feb 2005
Location: London
Posts: 218
There must be more to it than meets the eye. Size is conspicuous only by its absence in Add/Remove Programs.

EstimatedSize was worth a try though. Thx.
bnicer is offline   Reply With Quote
Old 6th March 2007, 10:42   #4
fishweasel
Junior Member
 
Join Date: Nov 2006
Posts: 19
The way it appears to me, is that windows checks the parent directory of the uninstaller and uses this directory size for display.

I currently have my uninstaller.exe in c:\temp
with the registry setting uninstallstring pointing to c:\temp\uninstall.exe. If i add for example a 100MB program into c:\temp - windows add/remove programs size increases by 100MB.

If i place the uninstaller into c:\ - and update the string to point to the new path c:\uninstall.exe - i no longer get a size, due to having no parent folder.

The size shown in add/remove programs seems to be the "size on disk" amount from folder properties.
fishweasel is offline   Reply With Quote
Old 6th March 2007, 13:20   #5
bnicer
Senior Member
 
Join Date: Feb 2005
Location: London
Posts: 218
Windows uses an algorithm to compute the size (imprecisely a lot of the time). Sometimes the parameters sought by the algorithm which derive from the name of your program and the files that are installed, are not present, so it would seem. According to the blog mentioned by Kichik (see above), you are able in such an event to override the algorithm by including your own dword in the reg that gives the exact size in KB: EstimatedSize.

To the annoyance of many, the dword value only applies if you install your software using an MSI installer. A search I did yesterday indicates that people have been trying without success to use EstimatedSize for some time; it only works with MSI.

In short, you can get the size by making sure the size algorithm finds the file/folder names it needs, or give up.
bnicer is offline   Reply With Quote
Old 19th November 2009, 18:41   #6
KEYofR
Junior Member
 
Join Date: Mar 2006
Location: Edison, NJ
Posts: 3
Send a message via ICQ to KEYofR
It works fine for me?
NSIS 2.45, Windows 7

Here are the relevant bits from my foo.nsi

code:

[...]

!define ARP "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}"

!include "FileFunc.nsh" ; for ${GetSize} for EstimatedSize registry entry

[...]

Section "Install"

; [...copy all files here, before GetSize...]

; get cumulative size of all files in and under install dir
; report the total in KB (decimal)
; place the answer into $0 (ignore $1 $2)
${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2

; Convert the decimal KB value in $0 to DWORD
; put it right back into $0
IntFmt $0 "0x%08X" $0

; Create/Write the reg key with the dword value
WriteRegDWORD HKLM "${ARP}" "EstimatedSize" "$0"

[...write the other reg keys in ${ARP}...]

SectionEnd

[...]

KEYofR is offline   Reply With Quote
Old 28th May 2010, 15:09   #7
bnicer
Senior Member
 
Join Date: Feb 2005
Location: London
Posts: 218
${GetSize} gets the real size, as opposed to the size on disk. As I understand it, the Add/Remove programs number, if done correctly, is the size on disk, the size needed by the software before running out of disk space in the worst case situation. The size on disk value varies according to the file system, FAT32 or NTFS, and the drive's cluster size apparently.

The NSIS documentation does not clearly state which of the two sizes the installer automatically calculates to determine the Space Required.

Maybe someone, who has that knowledge, could provide an answer. My guess is it's the real size.
bnicer is offline   Reply With Quote
Old 29th May 2010, 19:02   #8
bnicer
Senior Member
 
Join Date: Feb 2005
Location: London
Posts: 218
I had an idea -- a cut-and-paste job, like most of my ideas are. To obtain the size on disk, you can modify "GetSize" in FileFunc.nsh.

For documentation, see the NSIS user manual: E.1.3 GetSize.
Three variables are returned,

$var1 ; Result1: Size on disk
$var2 ; Result2: Sum of files
$var3 ; Result3: Sum of directories

PHP Code:
...

    
Push $8
    Push 
$9
    
insert code
    Push $R1
    Push $R2
    
end insert
    Push $R3
    Push $R4

...

    
FileFunc_GetSize_file:
    
StrCpy $R6 0
    StrCmp 
$5$'' +3
    IntOp $R4 $R4 
1
    
goto FileFunc_GetSize_findnext
    FileOpen 
$'$R8\$R7' r
    IfErrors 
+3
    FileSeek 
$9 0 END $R6
    FileClose 
$9
    StrCmp 
$'' +2
    IntCmp $R6 
$5 0 FileFunc_GetSize_findnext
    StrCmp 
$'' +2
    IntCmp $R6 
$6 0 0 FileFunc_GetSize_findnext
    IntOp $R4 $R4 
1
    
insert code
    IntOp $R6 $R6 
4096
    IntOp $R1 $R6 
4096
    StrCmp $R1 0 0 
+2
    StrCpy $R1 4096
    IntOp $R2 4096 
$R1
    IntOp $R6 $R6 
4096
    IntOp $R6 $R6 
$R2
    
end insert
    System
::Int64Op $R3 $R6
    Pop $R3

...

    
Pop $R4
    Pop $R3
    
insert code
    Pop $R2
    Pop $R1
    
end insert
    Pop 
$9
    Pop 
$8

... 
Size on disk is valid on NTFS formatted drives. All credit for the original "GetSize" goes to KichiK -- Function "FindFiles".
bnicer is offline   Reply With Quote
Old 3rd June 2010, 23:32   #9
CrushBug
Senior Member
 
Join Date: May 2005
Posts: 119
For Windows XP, I found that the only way to make Add/Remove display the estimated size was to also write the DWORD "WindowsInstaller" 1 - then it shows up. I don't know what other consequences are of setting that DWORD as we just discovered it a few minutes ago and are still testing.

edit: Dammit, now the presense of "WindowsInstaller" 1 is preventing the entry from showing entirely. Why is this so convoluted?

Last edited by CrushBug; 3rd June 2010 at 23:42. Reason: further pain discovered
CrushBug is offline   Reply With Quote
Old 24th February 2011, 10:22   #10
FlasH_10
Junior Member
 
Join Date: Feb 2011
Posts: 10
Is there any solution?
I write all uninstall information in HKLM ...\Uninstall. But it doesn't appear in Add/Remove software.
I use Windows XP SP2.
I read all information, but i don't get it. Has someone a clear solution?`
Thx
FlasH_10 is offline   Reply With Quote
Old 24th February 2011, 15:00   #11
Afrow UK
Moderator
 
Afrow UK's Avatar
 
Join Date: Nov 2002
Location: Surrey, England
Posts: 8,434
Did you miss the last post?

Stu
Afrow UK is offline   Reply With Quote
Old 24th February 2011, 17:25   #12
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 5,442
You should not be setting WindowsInstaller=1, it is a undocumented value and we don't know what it does

IntOp $PostCount $PostCount + 1
Anders is offline   Reply With Quote
Old 24th February 2011, 21:52   #13
Zinthose
Senior Member
 
Join Date: May 2009
Posts: 152
!DISCLAIMER!
This data is based on an undocumented registry entry and is only verified on Windows XP and is subject to change.
In Addition, the example only lists 32bit installations unless you tweak it to read from the 64bit registry.


Here's what I know...

Add and Remove Programs dialog lists the Size based from the corresponding ArpCache registry entry.

for example here is the my machines Notepad++ ArpCache Entry
PHP Code:
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Management\ARPCache\Notepad++]
"SlowInfoCache"=hex:28,02,00,00,01,00,00,00,00,50,ae,00,00,00,00,00,64,22,d7,\
  
82,ab,ae,cb,01,00,00,00,00,43,00,3a,00,5c,00,50,00,72,00,6f,00,67,00,72,00,\
  
61,00,6d,00,20,00,46,00,69,00,6c,00,65,00,73,00,5c,00,4e,00,6f,00,74,00,65,\
  
00,70,00,61,00,64,00,2b,00,2b,00,5c,00,6e,00,6f,00,74,00,65,00,70,00,61,00,\
  
64,00,2b,00,2b,00,2e,00,65,00,78,00,65,00,00,00,00,00,00,00,00,00,00,00,00,\
  
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,\
  
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,\
  
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,\
  
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,\
  
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,\
  
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,\
  
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,\
  
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,\
  
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,\
  
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,\
  
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,\
  
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,\
  
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,\
  
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,\
  
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,\
  
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,\
  
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,\
  
00,00,00,00,00,00,00,00
"Changed"=dword:00000000 
The important entry here is the "SlowInfoCache" value.

There is a pretty good and short article explaining it here: http://www.pcmag.com/article2/0,2817,1173443,00.asp

Here is an example of reading the data:

PHP Code:
!include "LogicLib.nsh"

OutFile Test.exe
ShowInstDetails show

Section
    
## Open Registry Key
        
System::Call "Advapi32::RegOpenKeyEx(i 0x80000002,t 'SOFTWARE\Microsoft\Windows\CurrentVersion\App Management\ARPCache\Notepad++',i 0,i 1,*i .r0)i .r3"
        
;DetailPrint "Result=$3"
        
${IfNotThen} $${|} Abort "Not ARPCache data is available." ${|}
    
    
## Check for existance of SlowInfoCache and validate tpye and size
        
System::Call "Advapi32::RegQueryValueEx(i r0,t 'SlowInfoCache',i 0,*i .r4,i 0,*i .r5)"
        
${IfNotThen} $0   ${|} Abort "Not SlowInfoCache data is available." ${|}
        ${
IfNotThen} $3   ${|} Abort "SlowInfoCache type is unexpected" ${|}
        ${
IfNotThen} $552 ${|} Abort "SlowInfoCache size unexpected"        ${|}
    
    
## Read SlowInfoCache Data
        
System::Alloc $5
        Pop 
$6
        System
::Call "Advapi32::RegQueryValueEx(i r0,t 'SlowInfoCache',i 0,*i n,i r6,*i r5)"
        
${IfNotThen} $0   ${|} Abort "Error reading SlowInfoCache data" ${|}
        
System::Call '*$6(&i4 .R1,&i4.R2,&i8.R3,&i4 .s,&i4 .s,&i4 .R5,&w524 .R6)'
        
    
## Convert the LastUsed FileTime to a Human readable format
        
System::Call `*(&i4 s,&i4 s)i .r7`
        
System::Free $6
    
        System
::Call "*(&i2, &i2, &i2, &i2, &i2, &i2, &i2, &i2) i .r3"
        
System::Call "Kernel32::FileTimeToSystemTime(i $7, i r3)"
        
System::Call "Kernel32::GetDateFormatA(i 0,i 0,i r3,t 'MM/dd/yyyy',t .R4,i ${NSIS_MAX_STRLEN})"
        
System::Free $7

    
## Close Registry Key
        
System::Call "Advapi32::RegCloseKey(i r0)i .r3"
        
${IfNotThen} $${|} Abort "Unable to close registry key" ${|}
        
    
## Format the InstallSize into a human readable format [bytes to megabytes]
        
Math::Script "R3=ff(R3/1048576.0,18)+' MB'"
        
    
## Display Results
        
DetailPrint "cbSize=$R1"
        
DetailPrint "HasName=$R2"
        
DetailPrint "InstallSize=$R3"
        
DetailPrint "LastUsed=$R4"
        
DetailPrint "Frequency=$R5"
        
DetailPrint "Name=$R6"
SectionEnd 
The Frequency value is an indication of the times the program is executed from a traceable shortcut from the Start Menu or Desktop. On the Add & Remove Programs dialog this is expressed as "Rarely", "Occasionally", or "Frequently". I'm not sure what values trigger what title but It could be calculated by tweaking a know value by increments. I think this is also tied to the LastUsed date so it might not be as simple hard value ranges.
Zinthose is offline   Reply With Quote
Old 14th May 2011, 09:04   #14
imgarfield
Junior Member
 
Join Date: May 2011
Posts: 2
Yep, the code KEYofR posted works (for me too) under win 7.

here is it again:

code:

!include "TextFunc.nsh"
${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2
IntFmt $0 "0x%08X" $0 #< conv to DWORD
WriteRegDWORD ${APP_UNINST_ROOT_KEY} "${APP_UNINST_KEY}" "EstimatedSize" "$0"



Later, in few days, I will test it on XP also.

Thanks
imgarfield is offline   Reply With Quote
Old 20th June 2011, 12:36   #15
imgarfield
Junior Member
 
Join Date: May 2011
Posts: 2
Quote:
Originally Posted by imgarfield View Post
Yep, the code KEYofR posted works (for me too) under win 7.

here is it again:

code:

!include "TextFunc.nsh"
${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2
IntFmt $0 "0x%08X" $0 #< conv to DWORD
WriteRegDWORD ${APP_UNINST_ROOT_KEY} "${APP_UNINST_KEY}" "EstimatedSize" "$0"



Later, in few days, I will test it on XP also.

Thanks
It seems to work under XP also.
imgarfield is offline   Reply With Quote
Old 2nd February 2013, 22:59   #16
bnicer
Senior Member
 
Join Date: Feb 2005
Location: London
Posts: 218
On the subject again.

Putting the size in the registry is one thing, getting the correct size is another.

The Required Space, I think, is calculated at compile-time based on the section sizes. You could query SectionGetSize ${id} $0, and the value returned would be a similar figure in Kb.

Is it size on disk? Size on disk is determined by the cluster size, which is your cluster size at compile-time.

If you want to replace the NSIS estimate with your own more accurate size estimate, should it be size on disk (in Kb), your disk, or should it be derived from bytes? The same question when you write the size to the registry, bytes or size on disk?

I would like to use size on disk.

My questions are, a) what does the NSIS (section size) estimate use? b) can you get the cluster size in a system call? GetVolumeInformation "Kernel32:: ... ?

Can anyone help? Thanks.
bnicer is offline   Reply With Quote
Old 3rd February 2013, 02:43   #17
bnicer
Senior Member
 
Join Date: Feb 2005
Location: London
Posts: 218
It occurs to me that the easiest way to find out the cluster size would be to write a 1 byte file and have the system tell you the size on disk. Only the system won't tell you. It'll tell you the file is 1 byte.

Is that correct?
bnicer is offline   Reply With Quote
Old 3rd February 2013, 04:38   #18
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 5,442
NSIS (and most other programs) don't handle cluster size/on disk size at all.

What if the destination directory is compressed? One of the files already exists and is sparse?

IntOp $PostCount $PostCount + 1
Anders is offline   Reply With Quote
Old 3rd February 2013, 10:53   #19
bnicer
Senior Member
 
Join Date: Feb 2005
Location: London
Posts: 218
You'd need that information too. Target compression as well as cluster size.

Also, if the cluster size is wrong, 8Kb instead of 4Kb, for instance, or if the destination is compressed, would the size-used estimate be more or less accurate than the bytes value?

I have never dealt with a compressed folder for an installation; I honestly don't know what happens. In case the folder is compressed, you could always revert to bytes, I'd say.

The user wants to know how much space a program takes up to avoid running out of space among other reasons, no doubt. Size on disk gives an accurate picture, provided it is accurate.

Do I withdraw the question?
bnicer is offline   Reply With Quote
Old 3rd February 2013, 14:46   #20
bnicer
Senior Member
 
Join Date: Feb 2005
Location: London
Posts: 218
Unlike NSIS and most programs I'm willing to gamble on compression, sparse files ... if it isn't too much trouble.

Cluster size?

I read about cluster size that it's hidden somewhere deep. Googled.
bnicer is offline   Reply With Quote
Old 4th February 2013, 13:35   #21
bnicer
Senior Member
 
Join Date: Feb 2005
Location: London
Posts: 218
Quote:
#!define LOGICAL ; "Space required" by the setup is calculated in bytes or physical size
; When LOGICAL is defined the logical size or the size on disk is calculated; to return an
; accurate value, the target volume has to be formatted in 4KB blocks
Skip down to the next code:

Quote:
!macro INI_READ KEY
!ifdef LOGICAL
ReadIniStr $3 ${TEMP1} "LOGICAL" "${KEY}"
!else
ReadIniStr $3 ${TEMP1} "PHYSICAL" "${KEY}"
!endif
!macroend
The ini file has two corresponding sections:

Quote:
[LOGICAL]
X=4
A=264
W=276
Q=8
All=23048
Win7=-2940
Win7N=-2940
WinV=-112
WinVN=-196
[PHYSICAL]
X=16
A=266696
W=281943
Q=4945
All=22044535
Win7=-3007822
Win7N=-3007811
WinV=-100856
WinVN=-195667
Getting the logical size (4KB) requires a modified version of KichiK's GetSize function/macro. I generate the ini file before compiling the setup.

I have one section for "Required space":

Quote:
SectionSetSize ${id1} 0 ; reset size estimate
SectionSetSize ${id2} $SIZE_2 ; the new size in KiB
The section id1 contains the install files. The id2 section is otherwise empty.

For the registry I do exactly what the previous posters described:

Quote:
SectionGetSize ${id2} ${TEMP1}
IntFmt ${TEMP1} "0x%08X" ${TEMP1}
WriteRegDword HKLM ${PRODUCT_UNINST_KEY} "EstimatedSize" ${TEMP1}
It hinges on cluster size. Without some means to test for it, LOGICAL must stay a pipe dream.

Everything is illogical.
bnicer is offline   Reply With Quote
Old 4th February 2013, 21:30   #22
bnicer
Senior Member
 
Join Date: Feb 2005
Location: London
Posts: 218
Sorry to keep bumping this thread.

I have made some headway and still have questions. Maybe someone can help.

I'm thinking of doing an NTFS check first.

StrCpy $0 $WINDIR 3 ; system drive
${GetFileSystem} $0 $0
${If} $0 == "NTFS"

I could proceed to checking the cluster size.

System::Call 'kernel32::GetDiskFreeSpace(i0,*i0r1,*i0r0,*i0r2,*i)'

Multiplying $0 * $1 does that. To be on the safe side, I'm making NTFS a condition, though GetDiskFreeSpace should work on older Windows and FAT systems.

This is where I have questions. Anders mentioned folder compression. Is folder compression something you can detect? What actually are the disk space consequences?

Sparse files, also mentioned, are probably less of a concern. Why would anyone wish to convert the files my setup installs into sparse files?

AFAIK, sparse files are used for disk images and p2p sharing. Is reinstalling possible?

Could someone push me in the right direction for folder compression? The fact it was raised lets me suspect that a solution is not easily come by.

Can you check if the destination directory is compressed?

I would really appreciate a yes or a no. Instructions wouldn't be bad either. Thanks.
bnicer is offline   Reply With Quote
Old 5th February 2013, 06:29   #23
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 5,442
To detect compression you can just check the file attribute...

IntOp $PostCount $PostCount + 1
Anders is offline   Reply With Quote
Old 5th February 2013, 19:02   #24
bnicer
Senior Member
 
Join Date: Feb 2005
Location: London
Posts: 218
The best I can do.

On the Directory page I can do a check for compression and, if compressed, the "Required space" changes to physical size, even if the other conditions for logical size are met.

However, if the user chooses to install to a new folder, meanwhile leaving the compressed folder alone, a second installation to the new folder, the "Required space" won't change back to logical size until after the user exits the page.

Only on clicking the Back button and returning to the Directory page would the user be aware of the new (old) size.

It's a small glitch, but one that's impossible to fix, unless I disallow multiple installations.

It seems almost better to stick with the original plan: always display logical size regardless of compression or not.

Compressed directories and sparse files have given me something to consider, and I am grateful for your advice, Anders.
bnicer is offline   Reply With Quote
Old 5th February 2013, 23:40   #25
bnicer
Senior Member
 
Join Date: Feb 2005
Location: London
Posts: 218
And thanks for GetFileAttributes.
bnicer is offline   Reply With Quote
Reply
Go Back   Winamp & Shoutcast Forums > Developer Center > NSIS Discussion

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump