Detecting if a program is already installed with NSIS
Asked Answered
H

4

14

I'm using NSIS to create an installer for a program, what is the best way to detect if this program is already installed? Also, since I'm running the installer from the autorun.inf, can I immediately quit the installer if it locates an installed copy? Is there a better way to do this?

Hilaryhilbert answered 28/1, 2009 at 18:18 Comment(0)
S
18

How about this. I had this in an old NSIS script laying around.

; Check to see if already installed
  ReadRegStr $R0 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\<YOUR-APP-NAME>" "UninstallString"
  IfFileExists $R0 +1 NotInstalled
  messagebox::show MB_DEFBUTTON4|MB_TOPMOST "<YOUR-APP-NAME>" \
    "0,103" \
    "<YOUR-APP-NAME> is already installed." \
    "Launch Uninstall" "Cancel"
    Pop $R1
  StrCmp $R1 2 Quit +1
  Exec $R0
Quit:
  Quit

NotInstalled:
Sino answered 28/1, 2009 at 22:8 Comment(3)
You mentioned Launch Uninstall. I could not really invoke Uninstall in my .nsi script by using this above code. Can you tell me how can i call Uninstall if my program is already installed?Anjelicaanjou
I had to change the messagebox::show line to MessageBox MB_YESNO "${YOUR_APP_NAME} is already installed. Uninstall the existing version?" /SD IDYES IDNO Quit.Ira
It is not always true. Some software does not have a direct <YOUR-APP-NAME> under Uninstall, eg, visual C++ redistributable. In such cases, we may have to iterate over all keys under Uninstall and to check the value data of the value name "DisplayName"Muticous
R
8

I've been using a slightly more sophisticated test which also checks the version of the installed software:

!define PRODUCT_VERSION "1.2.0"

!include "WordFunc.nsh"
  !insertmacro VersionCompare

Var UNINSTALL_OLD_VERSION

...

Section "Core System" CoreSystem
  StrCmp $UNINSTALL_OLD_VERSION "" core.files
  ExecWait '$UNINSTALL_OLD_VERSION'

core.files:

  ...
  WriteRegStr HKLM "Software\${PRODUCT_REG_KEY}" "" $INSTDIR
  WriteRegStr HKLM "Software\${PRODUCT_REG_KEY}" "Version" "${PRODUCT_VERSION}"
  ...
SectionEnd

...

Function .onInit
  ;Check earlier installation
  ClearErrors
  ReadRegStr $0 HKLM "Software\${PRODUCT_REG_KEY}" "Version"
  IfErrors init.uninst ; older versions might not have "Version" string set
  ${VersionCompare} $0 ${PRODUCT_VERSION} $1
  IntCmp $1 2 init.uninst
    MessageBox MB_YESNO|MB_ICONQUESTION "${PRODUCT_NAME} version $0 seems to be already installed on your system.$\nWould you like to proceed with the installation of version ${PRODUCT_VERSION}?" \
        IDYES init.uninst
    Quit

init.uninst:
  ClearErrors
  ReadRegStr $0 HKLM "Software\${PRODUCT_REG_KEY}" ""
  IfErrors init.done
  StrCpy $UNINSTALL_OLD_VERSION '"$0\uninstall.exe" /S _?=$0'

init.done:
FunctionEnd

You of course have to fill in the details, this only gives you a rough skeleton.

Ronnie answered 1/2, 2009 at 21:55 Comment(0)
R
3

After creating your uninstaller create a product name entry in registry

!define PRODUCT_UNINST_ROOT_KEY "HKLM"
!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANY_NAME} ${PRODUCT_NAME}"
Section -Post
  SetShellVarContext current
  WriteUninstaller "${UNINST_PATH}\uninst.exe"
  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)"

To see if the product is installed do

Function IsProductInstalled
  ClearErrors
  ReadRegStr $2 ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName"  
  StrCmp $2 "" exit

In your uninstall you should be doing

Section Uninstall
    DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
Robillard answered 2/7, 2009 at 4:41 Comment(0)
K
1

This is generally done by having NSIS insert a registry key for your product when it installs. It is then an easy manner to detect if that registry key is present and if so, bail

Ketron answered 28/1, 2009 at 18:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.