Add uninstall information to Add/Remove Programs: Difference between revisions

From NSIS Wiki
Jump to navigationJump to search
m (Reverted edits by 131.136.242.1 to last version by 192.88.166.35)
m (→‎How To Use: Version hint)
 
(20 intermediate revisions by 12 users not shown)
Line 4: Line 4:
Create a key with your product name under '''HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall''' to add entries to the "Add/Remove Programs" section in the Control Panel.
Create a key with your product name under '''HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall''' to add entries to the "Add/Remove Programs" section in the Control Panel.


For Windows NT (NT4/2000/XP), it's also possible to create the key in the '''HKCU''' hive, so it will only appear for the current user.
For Windows NT (NT4/2000/XP/Vista and higher), it's also possible to create the key in the '''HKCU''' hive, so it will only appear for the current user.


There are several values you can write to the key to give additional information about your application and the uninstaller.
There are several values you can write to the key to give additional information about your application and the uninstaller.
Line 19: Line 19:
== Required values ==
== Required values ==


*''DisplayName'' (string) - Name of the application
*''DisplayName'' (string) - Name of the application  
*''UninstallString'' (string) - Path and filename of the uninstaller. You should '''always''' quote the path to make sure spaces in the path will not disrupt Windows to find the uninstaller. To escape quotes, use single quotes unless a variables is included, in which case an escape sequence will have to be used.  The escape sequence is this: $\
*''UninstallString'' (string) - Path and filename of the uninstaller. You should '''always''' quote the path to make sure spaces in the path will not disrupt Windows to find the uninstaller. To escape quotes, use single quotes unless a variables is included, in which case an escape sequence will have to be used.  The escape sequence is this: $\


Line 48: Line 48:


== Optional values ==
== Optional values ==
See [http://windowssucks.wordpress.com/win-registry-uninstall-values/ here] for a more detailed description and hints. InstallLocation, Publisher and "ProductVersion" are documented as required to pass [https://msdn.microsoft.com/en-us/library/windows/desktop/mt637085#cleanReversibleInstall <abbr title="Windows App Certification Kit">WACK</abbr>] but InstallLocation does seem to be optional when testing. "ProductVersion" means VersionMajor+VersionMinor and/or DisplayVersion.


'''Supported on:''' ''Windows XP'', but note that it is perfectly allowed to add these entries to older versions of windows also, the additional info just does not show up.
'''Supported on:''' ''Windows XP'', but note that it is perfectly allowed to add these entries to older versions of windows also, the additional info just does not show up.


*''InstallLocation'' (string) - Installation directory ($INSTDIR)
*''InstallLocation'' (string) - Installation directory ($INSTDIR)
*''InstallDate'' (string) - Install date in yyyyMMdd format. [https://blogs.msdn.microsoft.com/oldnewthing/20180522-00/?p=98805 Windows uses the keys modified date] if not present.
*''DisplayIcon'' (string) - Path, filename and index of of the icon that will be displayed next to your application name
*''DisplayIcon'' (string) - Path, filename and index of of the icon that will be displayed next to your application name


Line 58: Line 61:
*''ModifyPath'' (string) - Path and filename of the application modify program
*''ModifyPath'' (string) - Path and filename of the application modify program
*''InstallSource'' (string) - Location where the application was installed from
*''InstallSource'' (string) - Location where the application was installed from
*''Language'' (DWORD) - $Language
   
   
*''ProductID'' (string) - Product ID of the application
*''ProductID'' (string) - Product ID of the application
*''Readme'' (string) - Path (File or URL) to readme information
*''RegOwner'' (string) - Registered owner of the application
*''RegOwner'' (string) - Registered owner of the application
*''RegCompany'' (string) - Registered company of the application
*''RegCompany'' (string) - Registered company of the application
Line 75: Line 80:
*''NoModify'' (DWORD) - 1 if uninstaller has no option to modify the installed application
*''NoModify'' (DWORD) - 1 if uninstaller has no option to modify the installed application
*''NoRepair'' (DWORD) - 1 if the uninstaller has no option to repair the installation
*''NoRepair'' (DWORD) - 1 if the uninstaller has no option to repair the installation
*''SystemComponent'' (DWORD) - Set 1 to prevents display of the application in the Programs List of the Add/Remove Programs in the Control Panel.


*''EstimatedSize'' (DWORD) - The size of the installed files (in KB)
*''EstimatedSize'' (DWORD) - The size of the installed files (in KB)
Line 85: Line 92:
'''Supported on:''' ''Windows XP Service Pack 2''.
'''Supported on:''' ''Windows XP Service Pack 2''.


*''ParentKeyName'' (string) - If the program is an update of a parent program, specify the parent program subkey name. If "OperatingSystem", it's an update for Windows.
*[https://docs.microsoft.com/en-us/windows/win32/shell/cpl-setprogramaccess#filtering-the-add-or-remove-programs-list ''ParentKeyName''] (string) - If the program is an update of a parent program, specify the parent program subkey name. If "OperatingSystem", it's an update for Windows.
*''ParentDisplayName'' (string) - If the program is an update of a parent program, specify the parent program name (as specified on the parent's "DisplayName").
*''ParentDisplayName'' (string) - If the program is an update of a parent program, specify the parent program name (as specified on the parent's "DisplayName").


== Computing EstimatedSize ==
== Computing EstimatedSize ==
Line 127: Line 133:
SectionGetSize $1 $0
SectionGetSize $1 $0
IntOp $GetInstalledSize.total $GetInstalledSize.total + $0
IntOp $GetInstalledSize.total $GetInstalledSize.total + $0
${Endif}
; Error flag is set when an out-of-bound section is referenced
${if} ${errors}
${break}
${Endif}
${Endif}
${Next}
${Next}
ClearErrors
Pop $1
Pop $1
Pop $0
Pop $0
Line 135: Line 148:
FunctionEnd
FunctionEnd
</highlight-nsis>
</highlight-nsis>
== With a MultiUser Installer ==
For an [http://nsis.sourceforge.net/Docs/MultiUser/Readme.html MultiUser] installer (that is, one that can install the application for all users or for only the current user), you can't always write to HKLM. To get around this, you can do something like the following:
<highlight-nsis>
!define UNINST_KEY \
  "Software\Microsoft\Windows\CurrentVersion\Uninstall\ImageMaker"
; ...
!define MULTIUSER_INSTALLMODE_COMMANDLINE
; ...
!include "MultiUser.nsh"
; ...
Section "Install"
  ; ...
  WriteRegStr SHCTX "${UNINST_KEY}" "DisplayName" "Image Maker"
  WriteRegStr SHCTX "${UNINST_KEY}" "UninstallString" \
    "$\"$INSTDIR\uninstall.exe$\" /$MultiUser.InstallMode"
  WriteRegStr SHCTX "${UNINST_KEY}" "QuietUninstallString" \
    "$\"$INSTDIR\uninstall.exe$\" /$MultiUser.InstallMode /S"
 
  WriteUninstaller $INSTDIR\uninstall.exe
  ; ...
SectionEnd
Section "Uninstall"
  ; ...
  DeleteRegKey SHCTX "${UNINST_KEY}"
SectionEnd
</highlight-nsis>
Key points (see also [http://forums.winamp.com/showthread.php?t=289071 this forum thread]):
* use SHCTX (SHELL_CONTEXT) instead of HKLM; SHCTX will be either HKLM (when installing for all users) or HKCU (when installing for the current user)
* the $MultiUser.InstallMode variable is either AllUsers or CurrentUser; passing it as part of the uninstall string lets the uninstaller know whether it should remove the uninstall key from HKLM or HKCU; in order to make this work, you have to define MULTIUSER_INSTALLMODE_COMMANDLINE


[[Category:Tutorials]]
[[Category:Tutorials]]

Latest revision as of 00:37, 17 September 2023

Author: Konrad (talk, contrib)


How To Use

Create a key with your product name under HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall to add entries to the "Add/Remove Programs" section in the Control Panel.

For Windows NT (NT4/2000/XP/Vista and higher), it's also possible to create the key in the HKCU hive, so it will only appear for the current user.

There are several values you can write to the key to give additional information about your application and the uninstaller.

Write a value using the WriteRegStr command (for strings) or WriteRegDWORD command (for DWORD values).

Example:

WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Product" \
                 "DisplayName" "Application Name"

Required values

  • DisplayName (string) - Name of the application
  • UninstallString (string) - Path and filename of the uninstaller. You should always quote the path to make sure spaces in the path will not disrupt Windows to find the uninstaller. To escape quotes, use single quotes unless a variables is included, in which case an escape sequence will have to be used. The escape sequence is this: $\

Consider this example. Your company is called 'Great Northern Software Co' and you are installing their latest super software 'Image Maker'. What you want to do is to have a new key created in the Software\Microsoft\Windows\CurrentVersion\Uninstall section of HKLM. The key will be the name of the software, and it will have two subkeys, one with the display name of the software and the other the location of the uninstall program.

WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\ImageMaker" \
                 "DisplayName" "Image Maker -- super software from Great Northern"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\ImageMaker" \
                 "UninstallString" "$\"$INSTDIR\uninstall.exe$\""

Once these are executed you will see the display name appear in the Add/Remove programs section of control panel.

Two things to point out. First, you must use backslashes. I do a lot of Java/Unix work, so I need to make this clear. And second, you should add a delete key command to your uninstaller section, so the name will be removed from the list when your uninstaller completes. If you don't do this your name will still be there, but windows will see this as a problem (ie it will say the entry is corrupt).

DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\ImageMaker"

Recommended values

  • QuietUninstallString (string) - Path and filename of the uninstaller and also a switch that uninstalls without a visible window. Most corporations need to install and uninstall silently. This ability should be included whenever possible. Similar to UninstallString, you should always quote the path to make sure spaces in the path will not disrupt Windows to find the uninstaller.
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\ImageMaker" \
                 "QuietUninstallString" "$\"$INSTDIR\uninstall.exe$\" /S"

Optional values

See here for a more detailed description and hints. InstallLocation, Publisher and "ProductVersion" are documented as required to pass WACK but InstallLocation does seem to be optional when testing. "ProductVersion" means VersionMajor+VersionMinor and/or DisplayVersion.

Supported on: Windows XP, but note that it is perfectly allowed to add these entries to older versions of windows also, the additional info just does not show up.

  • InstallLocation (string) - Installation directory ($INSTDIR)
  • InstallDate (string) - Install date in yyyyMMdd format. Windows uses the keys modified date if not present.
  • DisplayIcon (string) - Path, filename and index of of the icon that will be displayed next to your application name
  • Publisher (string) - (Company) name of the publisher
  • ModifyPath (string) - Path and filename of the application modify program
  • InstallSource (string) - Location where the application was installed from
  • Language (DWORD) - $Language
  • ProductID (string) - Product ID of the application
  • Readme (string) - Path (File or URL) to readme information
  • RegOwner (string) - Registered owner of the application
  • RegCompany (string) - Registered company of the application
  • HelpLink (string) - Link to the support website
  • HelpTelephone (string) - Telephone number for support
  • URLUpdateInfo (string) - Link to the website for application updates
  • URLInfoAbout (string) - Link to the application home page
  • DisplayVersion (string) - Displayed version of the application
  • VersionMajor (DWORD) - Major version number of the application
  • VersionMinor (DWORD) - Minor version number of the application
  • NoModify (DWORD) - 1 if uninstaller has no option to modify the installed application
  • NoRepair (DWORD) - 1 if the uninstaller has no option to repair the installation
  • SystemComponent (DWORD) - Set 1 to prevents display of the application in the Programs List of the Add/Remove Programs in the Control Panel.
  • EstimatedSize (DWORD) - The size of the installed files (in KB)
  • Comments (string) - A comment describing the installer package

If both NoModify and NoRepair are set to 1, the button displays "Remove" instead of "Modify/Remove".


Supported on: Windows XP Service Pack 2.

  • ParentKeyName (string) - If the program is an update of a parent program, specify the parent program subkey name. If "OperatingSystem", it's an update for Windows.
  • ParentDisplayName (string) - If the program is an update of a parent program, specify the parent program name (as specified on the parent's "DisplayName").

Computing EstimatedSize

It's strongly recomended to include an EstimatedSize field in your unninstall entry, so that correct size information appears in the "Add or Remove Programs" applet. Without such an entry Windows will turn to guessing, and the heuristics involved are quite fragile.

Method 1: Use ${GetSize} to fill in the EstimatedSize value. This assumes the simple case where there is one main directory with most of your files (including subdirs):

 !define ARP "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}"
 !include "FileFunc.nsh"
 
 Section "Install"
 
 ; [...copy all files here, before GetSize...]
 
 ${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2
 IntFmt $0 "0x%08X" $0
 WriteRegDWORD HKLM "${ARP}" "EstimatedSize" "$0"
 
 SectionEnd

Method 2: Compute the sum of all components installed sizes. This method is much faster, especialy for a large program, but it requires correct size info stored in the section itself. For example, if the section generates large data files in the install directory, and these files are not included via File but generated at installer runtime, then you need to account for the extra space using AddSize

!include LogicLib.nsh
 
; Return on top of stack the total size of the selected (installed) sections, formated as DWORD
; Assumes no more than 256 sections are defined
Var GetInstalledSize.total
Function GetInstalledSize
	Push $0
	Push $1
	StrCpy $GetInstalledSize.total 0
	${ForEach} $1 0 256 + 1
		${if} ${SectionIsSelected} $1
			SectionGetSize $1 $0
			IntOp $GetInstalledSize.total $GetInstalledSize.total + $0
		${Endif}
 
		; Error flag is set when an out-of-bound section is referenced
		${if} ${errors}
			${break}
		${Endif}
	${Next}
 
	ClearErrors
	Pop $1
	Pop $0
	IntFmt $GetInstalledSize.total "0x%08X" $GetInstalledSize.total
	Push $GetInstalledSize.total
FunctionEnd

With a MultiUser Installer

For an MultiUser installer (that is, one that can install the application for all users or for only the current user), you can't always write to HKLM. To get around this, you can do something like the following:

!define UNINST_KEY \
  "Software\Microsoft\Windows\CurrentVersion\Uninstall\ImageMaker"
; ...
!define MULTIUSER_INSTALLMODE_COMMANDLINE
; ...
!include "MultiUser.nsh"
; ...
Section "Install"
  ; ...
 
  WriteRegStr SHCTX "${UNINST_KEY}" "DisplayName" "Image Maker"
  WriteRegStr SHCTX "${UNINST_KEY}" "UninstallString" \
    "$\"$INSTDIR\uninstall.exe$\" /$MultiUser.InstallMode"
  WriteRegStr SHCTX "${UNINST_KEY}" "QuietUninstallString" \
    "$\"$INSTDIR\uninstall.exe$\" /$MultiUser.InstallMode /S"
 
  WriteUninstaller $INSTDIR\uninstall.exe
 
  ; ...
SectionEnd
 
Section "Uninstall"
  ; ...
 
  DeleteRegKey SHCTX "${UNINST_KEY}"
SectionEnd

Key points (see also this forum thread):

  • use SHCTX (SHELL_CONTEXT) instead of HKLM; SHCTX will be either HKLM (when installing for all users) or HKCU (when installing for the current user)
  • the $MultiUser.InstallMode variable is either AllUsers or CurrentUser; passing it as part of the uninstall string lets the uninstaller know whether it should remove the uninstall key from HKLM or HKCU; in order to make this work, you have to define MULTIUSER_INSTALLMODE_COMMANDLINE