Delta Engine Blog

All about multiplatform and game development

Using Nullsofts Installer System (NSIS) to create Setups for XNA Games

After updating so much on my blog the last 2 days and posting all the unfinished posts I had prepared a few weeks ago I finally reach the last important one I wanted to make. But due the fact that I will fly to the MVP summit tomorrow I better not stay away too long. Hopefully this post still contains all the vital information. Let's get started.

First of all you need the latest version of the free NSIS (Nullsoft Installer System):
There are TONS of information on that website and if you are new to the NSIS scripts be sure to read at least the quick start guide (called simple tutorials) and use the NSIS Forums search feature for more specific problems and questions.

Good, now just let us go quickly through the .nsi file I currently use for all my XNA Game Setups. Please note that this file has evolved over many years (I guess I started using NSIS in 2002) and parts might not be simple to read or even be how it is done today, but the script was always a very helpful and quick way to create Setups for me. While detecting all the requirements to make XNA work is not a piece of cake many NSIS tutorials helped me to figure all the parts out.

The following .nsi script is from the previous blog post "Loading Collada Models in XNA 2.0 and doing Skinning and Animation" and was used to build the XnaSkinningColladaModelsSetup.exe (2.2 MB) file. If you want to use it for your own XNA Game project just use a text-editor and replace "XnaSkinningColladaModels" with your own game name (it occurs many times in the file). Also create a .bmp file with the name of your game for the setup header (check MUI_HEADERIMAGE_BITMAP) or comment the 2 Header Image lines out with a ; or # if you do not want any header image. All files are grabbed from the /Release directory and will be installed to the target (make sure that you only have files in the /Release directory that you want to have deployed). This should be already enough information to make your setup work, the rest of this article will just go into the details of the script.

The XnaSkinningColladaModelsSetup.nsi file is organized in 6 parts (Initialization, onInit, File section, Optional sections, Helper functions and Uninstall):
  • Initialization: Just sets all the names, the required modules, and how the setup is displayed to the user (all the pages, see MUI_PAGE). Version information and file information are also a vital part here and you should enter some meaningful values here. Also put any language strings for different languages (this installer is just using english text) at text part of the initialization code.
    !include "MUI.nsh"
    SetCompressor /SOLID lzma
    
    ;Name and file
    Name "XnaSkinningColladaModels"
    OutFile "XnaSkinningColladaModelsSetup.exe"
    
    ;Default installation folder
    InstallDir "$PROGRAMFILES\XnaSkinningColladaModels"
    
    ;Get installation folder from registry if available
    InstallDirRegKey HKLM "Software\XnaSkinningColladaModels" ""
    
    !define MUI_COMPONENTSPAGE_NODESC
    
    ;Interface Settings
    !define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\modern-install-blue.ico"
    !define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\modern-uninstall-blue.ico"
    !define MUI_HEADERIMAGE
    !define MUI_HEADERIMAGE_BITMAP "XnaSkinningColladaModels.bmp"
    !define MUI_HEADERIMAGE_UNBITMAP "XnaSkinningColladaModels.bmp"
    !define MUI_ABORTWARNING
    
    ;Pages
    !insertmacro MUI_PAGE_WELCOME
    !insertmacro MUI_PAGE_COMPONENTS
    !insertmacro MUI_PAGE_DIRECTORY
    !insertmacro MUI_PAGE_INSTFILES
    
    !insertmacro MUI_UNPAGE_CONFIRM
    !insertmacro MUI_UNPAGE_INSTFILES
    
    ;Languages
    !insertmacro MUI_LANGUAGE "English"
    
    ;Version Information
    VIProductVersion "1.0.0.0"
    VIAddVersionKey /LANG=${LANG_ENGLISH} "ProductName" "XnaSkinningColladaModels"
    VIAddVersionKey /LANG=${LANG_ENGLISH} "Comments" "XnaSkinningColladaModels project, see http://BenjaminNitschke.com"
    VIAddVersionKey /LANG=${LANG_ENGLISH} "CompanyName" "BenjaminNitschke.com"
    VIAddVersionKey /LANG=${LANG_ENGLISH} "LegalCopyright" "© BenjaminNitschke.com 2007"
    VIAddVersionKey /LANG=${LANG_ENGLISH} "FileDescription" "XnaSkinningColladaModels"
    VIAddVersionKey /LANG=${LANG_ENGLISH} "FileVersion" "1.0.0.0"
    
    ; The text to prompt the user to enter a directory
    ComponentText "This will install XnaSkinningColladaModels for XNA 2.0."
    
    UninstallText "This will remove XnaSkinningColladaModels for XNA 2.0 from your computer."
    
    ; New .NET Check function, we want at least v2.0
    !define DOT_MAJOR "2"
    !define DOT_MINOR "0"
    
    ; The text to prompt the user to enter a directory
    DirText "Please select a directory for the installation:"
    
    AutoCloseWindow true
    

  • .onInit: This method is executed before the installer is run and can perform any checks you like. I just try to find out if any c:\games directory exists in several languages, if it does, then we can use it, else just use the default c:\program files location.
    
    Function .onInit
        ;First try to find "Games" (eng), "Spiele" (ger), "jeux" (fr),
        ; "giochi" (ita), "jogos" (port) or "spelen" (nl) directory!
        StrCpy $R1 "C:\Games"
        IfFileExists $R1 UseIt
        StrCpy $R1 "C:\Spiele"
        IfFileExists $R1 UseIt
        StrCpy $R1 "C:\jeux"
        IfFileExists $R1 UseIt
        StrCpy $R1 "C:\giochi"
        IfFileExists $R1 UseIt
        StrCpy $R1 "C:\jogos"
        IfFileExists $R1 UseIt
        StrCpy $R1 "C:\spelen"
        IfFileExists $R1 UseIt
        Goto DontUseIt
    UseIt:
        StrCpy $INSTDIR "$R1\XnaSkinningColladaModels"
    DontUseIt:
    FunctionEnd
    

  • File section: This is the most important section and always required because it tells the setup where the files come from (in our case from the Release sub directory) and where they should be installed (in #INSTDIR).
    
    ; The stuff to install
    Section "XnaSkinningColladaModels"
      SectionIn RO
      ; Set output path to the installation directory.
      SetOutPath $INSTDIR
      ; Put file there
      File /r "Release\*.*"
     
      ; Write the installation path into the registry
      WriteRegStr HKLM "SOFTWARE\XnaSkinningColladaModels" "Install_Dir" "$INSTDIR"
      WriteRegStr HKLM "SOFTWARE\XnaSkinningColladaModels" "Version" "v1.0"
      ; Write the uninstall keys for Windows
      WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\XnaSkinningColladaModels" "DisplayName" "XnaSkinningColladaModels"
      WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\XnaSkinningColladaModels" "UninstallString" "$INSTDIR\uninstall.exe $INSTDIR"
      WriteUninstaller "uninstall.exe"
    SectionEnd
    

  • Optional sections: These sections are optional and the user can decide not to create desktop shortcuts, not to install XNA 2.0 if it is not found, etc. I usually leave them all on by default because they make sense. Most important here are the DirectX and XNA prequisites sections, which make a lot of use of the helper functions.
    
    ; Optional sections
    Section "Create Start-Menu shortcuts"
      StrCpy $R1 "$SMPROGRAMS\XnaSkinningColladaModels"
      CreateDirectory "$R1"
      CreateShortCut "$R1\XnaSkinningColladaModels.lnk" "$INSTDIR\XnaSkinningColladaModels.exe" "" "$INSTDIR\XnaSkinningColladaModels.exe" 0 "" "" "XnaSkinningColladaModels"
      CreateShortCut "$R1\XnaSkinningColladaModels Uninstall.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0 "" "" "Uninstall XnaSkinningColladaModels."
      CreateShortCut "$R1\BenjaminNitschke.com.lnk" "http://BenjaminNitschke.com" "" "" 0 "" "" "BenjaminNitschke.com website from the creator of this game"
    SectionEnd
    
    Section "Create Desktop shortcuts"
      CreateShortCut "$DESKTOP\XnaSkinningColladaModels.lnk" "$INSTDIR\XnaSkinningColladaModels.exe" "" "$INSTDIR\XnaSkinningColladaModels.exe" 0
    SectionEnd
    
    Section "Check for .NET 2.0 Framework (required)"
      Call IsDotNETInstalled
      Pop $0
      StrCmp $0 1 found.NETFramework no.NETFramework
    no.NETFramework:
    ;MessageBox MB_OK ".NET was not found .."
      ; First of all check for correct IE version!
      Call CheckForCorrectIEVersion
      ; First check if DotNetFx.exe exists
      IfFileExists "$EXEDIR\DotNetFx.exe" 0 DotNetFileNotFound
      ReadRegStr $R0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" "AutoAdminLogon"
      ExecWait '"$EXEDIR\DotNetFx.exe" /q'
      StrCmp $R0 1 RestoreAutoLogon End
    RestoreAutoLogon:
      WriteRegStr HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" "AutoAdminLogon" "1"
      goto End
    
      ; If DotNetFx.exe was not found, try downloading online
    DotNetFileNotFound:
      MessageBox MB_YESNOCANCEL|MB_ICONQUESTION ".NET Framework 2.0 was not found. XnaSkinningColladaModels will not run without it! $\r$\nWould you like to automatically download and install it? $\r$\n $\r$\nChoose Yes for an automatic download and installation. $\r$\nChoose No, you want to select the download yourself (e.g. locally if already downloaded). $\r$\nMicrosoft's .NET Framework Download page will open up! $\r$\nChoose cancel to abort any action here, you will have to install the .NET Framework (2.0) $\r$\nyourself. That can be done for example automatically by the Windows Update $\r$\n(just go to http://windowsupdate.microsoft.com )" IDYES DL IDNO IndirectDL
      goto End
      IndirectDL:
        ExecShell open "http://www.microsoft.com/downloads/details.aspx?FamilyID=0856eacb-4362-4b0d-8edd-aab15c5e04f5" "" SW_SHOWNORMAL
        goto End
      DL:
        Call ConnectInternet ;Make an internet connection (if no connection available)
    
        StrCpy $2 "$TEMP\DotNetFX_Setup.exe"
        NSISdl::download http://download.microsoft.com/download/5/6/7/567758a3-759e-473e-bf8f-52154438565a/dotnetfx.exe $2
        Pop $0
        StrCmp $0 success success
          SetDetailsView show
          DetailPrint "download failed: $0"
          MessageBox MB_OK ".NET could not be installed, download was aborted. Please install .NET yourself! $\r$\nRest of the installation went ok, you just need .NET 2.0 to start XnaSkinningColladaModels!"
          goto End
        success:
          ; Install, in quiet mode (will do everything automatically)
          ExecWait '"$2" /q'
          Delete $2
      
        goto End
    found.NETFramework:
    ;MessageBox MB_OK ".NET is installed, very good ^^"
    End:
    SectionEnd
    
    Section "Check for DirectX 9.0c (November 2007) (required)"
      call IsDirectX9Installed
      pop $0
      StrCmp $R1 1 maybefound.DirectX9 notFound.DirectX9
    maybefound.DirectX9:
        ; Check if managed directx december 2006 is installed!
        IfFileExists "$WINDIR\Microsoft.NET\DirectX for Managed Code\1.0.2911.0" found.DirectX9  
    notFound.DirectX9:
    ;MessageBox MB_OK "DirectX9 or better was not found!"
      ; First check if a file "dx90update_redist.exe" exists
      IfFileExists "$EXEDIR\directx_nov2007_redist.exe" 0 DX9RedistFileNotFoundTest1
      ExecWait '"$EXEDIR\directx_nov2007_redist.exe" /Q /T:"$TEMP" /C'
      ; Now install DirectX9
      ExecWait "$TEMP\dxsetup.exe"
      goto End
    DX9RedistFileNotFoundTest1:
        ; Check again in temp folder
      IfFileExists "$TEMP\directx_nov2007_redist.exe" 0 DX9RedistFileNotFound
      ExecWait '"$TEMP\directx_nov2007_redist.exe" /Q /T:"$TEMP" /C'
      ; Now install DirectX9
      ExecWait "$TEMP\dxsetup.exe"
      goto End
      ; If that failed, ask user!
    DX9RedistFileNotFound:
      MessageBox MB_YESNOCANCEL|MB_ICONQUESTION "DirectX9.0c November 2007 or better was not found. XnaSkinningColladaModels needs DirectX9.0c and Managed DirectX runtimes to run. $\r$\nWould you like to automatically download and install it? $\r$\n $\r$\nChoose Yes for an automatic download and installation. $\r$\nChoose No, you want to select the download yourself (e.g. in another language than english). $\r$\nMicrosoft's DirectX Download page will open up! $\r$\nChoose cancel to abort any action here, you will have to install DirectX yourself." IDYES DL IDNO IndirectDL
      goto End
    IndirectDL:
      ExecShell open "http://www.microsoft.com/downloads/details.aspx?familyid=1A2393C0-1B2F-428E-BD79-02DF977D17B8" "" SW_SHOWNORMAL 
      goto End
    DL:
      Call ConnectInternet ;Make an internet connection (if no connection available)
    
      StrCpy $2 "$TEMP\directx_nov2007_redist.exe"
      NSISdl::download http://download.microsoft.com/download/c/6/a/c6af7ea3-f85c-4fef-a475-5810f82def1f/directx_nov2007_redist.exe $2
    
      Pop $0
      StrCmp $0 success success
        SetDetailsView show
        DetailPrint "download failed: $0"
        MessageBox MB_OK "DirectX could not be installed, download was aborted. Please install DirectX yourself! $\r$\nRest of the installation went ok, you just need DirectX 9.0c December 2006 to start XnaSkinningColladaModels!"
        goto End
      success:
        ; Install quietly into temp folder
        ExecWait '"$2" /Q /T:"$TEMP" /C'
        ; Now install DirectX9
        ExecWait "$TEMP\dxsetup.exe"
        ; Yeah, we made it!
        ;why delete, maybe user wants to keep it ^^ Delete $2
      goto End
    found.DirectX9:
    ;MessageBox MB_OK "Found DirectX9 or better .."
      goto End
    End:
    SectionEnd
    
    Section "Check for XNA 2.0 (December 2007) (required)"
      call IsXNAInstalled
      pop $0
      StrCmp $R1 1 found.XNA notFound.XNA
    notFound.XNA:
      MessageBox MB_YESNOCANCEL|MB_ICONQUESTION "XNA 2.0 (December 2007) or better was not found. The XnaSkinningColladaModels needs the XNA 2.0 runtimes to run. $\r$\nWould you like to automatically download and install it? $\r$\n $\r$\nChoose Yes for an automatic download and installation. $\r$\nChoose No, you want to select the download yourself (e.g. in another language than english). $\r$\nMicrosoft's XNA Download page will open up! $\r$\nChoose cancel to abort any action here, you will have to install XNA yourself." IDYES DL IDNO IndirectDL
      goto End
    IndirectDL:
      ExecShell open "http://www.microsoft.com/downloads/details.aspx?FamilyID=15fb9169-4a25-4dca-bf40-9c497568f102" "" SW_SHOWNORMAL 
      goto End
    DL:
      Call ConnectInternet ;Make an internet connection (if no connection available)
    
      StrCpy $2 "$TEMP\xnafx20_redist.msi"
      NSISdl::download "http://download.microsoft.com/download/b/8/a/b8a1f45a-63e6-4d1f-9c03-55a83d30ee3b/xnafx20_redist.msi" $2
    
      Pop $0
      StrCmp $0 success success
        SetDetailsView show
        DetailPrint "download failed: $0"
        MessageBox MB_OK "XNA 2.0 could not be installed, download was aborted. Please install XNA 2.0 yourself! $\r$\nRest of the installation went ok, you just need XNA 2.0 (December 2007) to start the XnaSkinningColladaModels!"
        goto End
      success:
        ; Install XNA, quietly does not work on vista for some reason ...
        ExecWait 'msiexec /i "$2" /q'
        ; Yeah, we made it!
        ;why delete, maybe user wants to keep it ^^ Delete $2
      goto End
    found.XNA:
    ;MessageBox MB_OK "Found XNA 2.0 or better .."
      goto End
    End:
    SectionEnd
    
    Section "-Ask some questions"
      MessageBox MB_YESNO|MB_ICONQUESTION "Start the XnaSkinningColladaModels now?" IDYES StartRC
      goto DontStart
    StartRC:
      Exec "$INSTDIR\XnaSkinningColladaModels.exe"
    DontStart:
    SectionEnd
    

  • Helper functions: These little helpers are the utitilies to make all the complex XNA installation steps work. They go through all the steps from making sure .NET is installed, installing it automatically for you if you like, even opening up an internet connection if you are on dialup, checking all the prequisites for installing .NET (like having at least IE 5) and then finally install all the XNA 2.0 and DirectX stuff that is required to run your game on top of that. All without ever leaving the installer and tested on many platforms. I usually do not touch this code unless I have to update some links or include a newer version of .NET, DirectX or XNA. I tried to comment my work, but understanding this script part will not be easy. Just do not expect that any changes you make here will be safe. You need to do a lot of testing in order to add additional functionality here.
    ; IsDotNETInstalled
    ;
    ; Usage:
    ;   Call IsDotNETInstalled
    ;   Pop $0
    ;   StrCmp $0 1 found.NETFramework no.NETFramework
    ;Function IsDotNETInstalled
    ;   Push $0
    ;   Push $1
    ;   Push $2
    ;   Push $3
    ;   Push $4
    ;
    ;   ReadRegStr $4 HKEY_LOCAL_MACHINE \
    ;     "Software\Microsoft\.NETFramework" "InstallRoot"
    ;   # remove trailing back slash
    ;   Push $4
    ;   Exch $EXEDIR
    ;   Exch $EXEDIR
    ;   Pop $4
    ;   # if the root directory doesn't exist .NET is not installed
    ;   IfFileExists $4 0 noDotNET
    ;
    ;   StrCpy $0 0
    ;
    ;   EnumStart:
    ;
    ;     EnumRegKey $2 HKEY_LOCAL_MACHINE \
    ;       "Software\Microsoft\.NETFramework\Policy"  $0
    ;     IntOp $0 $0 + 1
    ;     StrCmp $2 "" noDotNET
    ;
    ;     StrCpy $1 0
    ;
    ;     EnumPolicy:
    ;
    ;       EnumRegValue $3 HKEY_LOCAL_MACHINE \
    ;         "Software\Microsoft\.NETFramework\Policy\$2" $1
    ;       IntOp $1 $1 + 1
    ;        StrCmp $3 "" EnumStart
    ;         IfFileExists "$4\$2.$3" foundDotNET EnumPolicy
    ;
    ;   noDotNET:
    ;     StrCpy $0 0
    ;     Goto done
    ;
    ;   foundDotNET:
    ;     StrCpy $0 1
    ;
    ;   done:
    ;     Pop $4
    ;     Pop $3
    ;     Pop $2
    ;     Pop $1
    ;     Exch $0
    ;FunctionEnd
    
    ; Call IsDotNetInstalled
    ; This function will abort the installation if the required version 
    ; or higher version of the .NETFramework is not installed.  Place it in
    ; either your .onInit function or your first install section before 
    ; other code.
    Function IsDotNETInstalled
      Push $0
      Push $1
      Push $2
      Push $3
      Push $4
    
      StrCpy $0 "0"
      StrCpy $1 "SOFTWARE\Microsoft\.NETFramework" ;registry entry to look in.
      StrCpy $2 0
    
      StartEnum:
        ;Enumerate the versions installed.
        EnumRegKey $3 HKLM "$1\policy" $2
    
    ;MessageBox MB_OK "EnumRegKey $3"
        ;If we don't find any versions installed, it's not here.
        StrCmp $3 "" noDotNet notEmpty
    
        ;We found something.
        notEmpty:
          ;Find out if the RegKey starts with 'v'.  
          ;If it doesn't, goto the next key.
          StrCpy $4 $3 1 0
          StrCmp $4 "v" +1 goNext
          StrCpy $4 $3 1 1
          
          ;It starts with 'v'.  Now check to see how the installed major version
          ;relates to our required major version.
          ;If it's equal check the minor version, if it's greater, 
          ;we found a good RegKey.
          IntCmp $4 ${DOT_MAJOR} +1 goNext yesDotNetReg
          ;Check the minor version.  If it's equal or greater to our requested 
          ;version then we're good.
          StrCpy $4 $3 1 3
          IntCmp $4 ${DOT_MINOR} yesDotNetReg goNext yesDotNetReg
    
        goNext:
          ;Go to the next RegKey.
          IntOp $2 $2 + 1
          goto StartEnum
    
      yesDotNetReg:
    ;MessageBox MB_OK "DotNet Reg stuff was found!"
        ;Now that we've found a good RegKey, let's make sure it's actually
        ;installed by getting the install path and checking to see if the 
        ;mscorlib.dll exists.
        EnumRegValue $2 HKLM "$1\policy\$3" 0
        ;$2 should equal whatever comes after the major and minor versions 
        ;(ie, v1.1.4322)
        StrCmp $2 "" noDotNet
        ReadRegStr $4 HKLM $1 "InstallRoot"
        ;Hopefully the install root isn't empty.
        StrCmp $4 "" noDotNet
        ;build the actuall directory path to mscorlib.dll.
        StrCpy $4 "$4$3.$2\mscorlib.dll"
    ;MessageBox MB_OK "Does $4 exists?"
        IfFileExists $4 yesDotNet noDotNet
    
      noDotNet:
    ;MessageBox MB_OK "DotNet was not found .."
        StrCpy $0 0
        Goto done
    
      yesDotNet:
    ;MessageBox MB_OK "DotNet stuff was found!"
        StrCpy $0 1
      done:
        Pop $4
        Pop $3
        Pop $2
        Pop $1
        Exch $0
    FunctionEnd
    
    Function ConnectInternet
      ClearErrors
      Dialer::AttemptConnect
      IfErrors noie3
    
      Pop $R0
      StrCmp $R0 "online" connected
        Strcpy $R0 "Cannot connect to the internet."
        MessageBox MB_OK|MB_ICONSTOP $R0
        Quit
    
      noie3:
    
      ; IE3 not installed
      MessageBox MB_OK|MB_ICONINFORMATION "Please connect to the internet now."
    
      connected:
    FunctionEnd
    
    ;GetIEVersion
    ; Based on Yazno's function, [url]http://yazno.tripod.com/powerpimpit/[/url]
    ; Returns on top of stack
    ; 1-6 (Installed IE Version)
    ; or
    ; '' (IE is not installed)
    ;
    ; Usage:
    ;   Call GetIEVersion
    ;   Pop $R0
    ;   ; at this point $R0 is "5" or whatnot
    Function GetIEVersion
       Push $R0
       ClearErrors
       ReadRegStr $R0 HKLM "Software\Microsoft\Internet Explorer" "Version"
       IfErrors lbl_123 lbl_456
    
       lbl_456: ; ie 4+
          ReadRegStr $R0 HKLM "Software\Microsoft\Internet Explorer\Version Vector" "IE"   
          Strcpy $R0 $R0 4
          Goto lbl_done
    
       lbl_123: ; older ie version
          ClearErrors
          ReadRegStr $R0 HKLM "Software\Microsoft\Internet Explorer" "IVer"
          IfErrors lbl_error
    
          StrCpy $R0 $R0 3
          StrCmp $R0 '100' lbl_ie1
          StrCmp $R0 '101' lbl_ie2
          StrCmp $R0 '102' lbl_ie2
    
          StrCpy $R0 '3' ; default to ie3 if not 100, 101, or 102.
          Goto lbl_done
          lbl_ie1:
             StrCpy $R0 '1'
             Goto lbl_done
          lbl_ie2:
             StrCpy $R0 '2'
             Goto lbl_done
          lbl_error:
             StrCpy $R0 ''
          lbl_done:
       Exch $R0
    FunctionEnd
    
    ; Checks for current IE version and will try to call
    ; IE6Setup.exe if it exists, otherwise prompt the user
    ; to install it for himself (at least IE5.01 is required for .NET)
    Function CheckForCorrectIEVersion
       Call GetIEVersion
       Pop $R0
       Push $R1
       StrCpy $R1 $R0 1
       StrCmp $R1 '6' lbl_IEOK
       StrCmp $R1 '5' lbl_IE5
       StrCmp $R1 '4' lbl_IEKO
       StrCmp $R1 '2' lbl_IEKO
       StrCmp $R1 '3' lbl_IEKO
       StrCmp $R1 '1' lbl_IEKO
    
       lbl_IE5:
          StrCmp $R0 '5.00' lbl_IEKO
          Goto lbl_IEOK
       lbl_IEKO:
    ;MessageBox MB_OK "IE5.01 or better was not found!"
          ; First check if ie6setup.exe exists
          IfFileExists "$EXEDIR\Setups\ie6sp1\ie6setup.exe" 0 IE6FileNotFound
          ExecWait '"$EXEDIR\Setups\ie6sp1\ie6setup.exe"'
          goto lbl_IEOK
          ; If DotNetFx.exe was not found, try downloading online
        IE6FileNotFound:
          MessageBox MB_YESNOCANCEL|MB_ICONQUESTION "IE5.01 or better was not found. .NET can't be installed without it! $\r$\nWould you like to automatically download and install it? $\r$\n $\r$\nChoose Yes for an automatic download and installation. $\r$\nChoose No, you want to select the download yourself (e.g. in another language than english). $\r$\nMicrosoft's .NET Framework Download page will open up! $\r$\nChoose cancel to abort any action here, you will have to install IE5.01 or better$\r$\nyourself, that can be done for example automatically by the Windows Update $\r$\n(just go to http://windowsupdate.microsoft.com )" IDYES DL IDNO IndirectDL
          goto lbl_IEOK
         IndirectDL:
          ExecShell open "http://www.microsoft.com/downloads/details.aspx?FamilyID=1e1550cb-5e5d-48f5-b02b-20b602228de6" "" SW_SHOWNORMAL
          goto lbl_IEOK
         DL:
          Call ConnectInternet ;Make an internet connection (if no connection available)
          StrCpy $2 "$TEMP\IE6Setup.exe"
          NSISdl::download http://download.microsoft.com/download/ie6sp1/finrel/6_sp1/W98NT42KMeXP/EN-US/ie6setup.exe $2
          Pop $0
          StrCmp $0 success success
          SetDetailsView show
          DetailPrint "download failed: $0"
          MessageBox MB_OK "IE6Setup could not be installed, download was aborted. Please install IE and .NET yourself! $\r$\nRest of the installation went ok, you just need IE for .NET to start XnaSkinningColladaModels!"
          goto lbl_IEOK
        success:
          ; Install, in quiet mode (will do everything automatically)
          ExecWait '"$2"'
          Delete $2
       lbl_IEOK:
    ;MessageBox MB_OK "IE5.01 or better was found .."
    FunctionEnd
    
    ; Check if DirectX9 or better is installed,
    ; will return $0 1 then, else $0 is 0.
    Function IsDirectX9Installed
      Push $0
    
      ReadRegStr $0 HKLM "SOFTWARE\Microsoft\DirectX" "Version"
      StrCpy $1 $0 4 3
      IntCmp $1 9 found.DirectX9 notFound.DirectX9 found.DirectX9
    notFound.DirectX9:
    ;MessageBox MB_OK "can't find direct9"
      StrCpy $0 0
      Goto done
    
    found.DirectX9:
    ;MessageBox MB_OK "found direct9 or better"
      StrCpy $0 1
    
    done:
    ;MessageBox MB_OK "direct9 found value: $0"
      StrCpy $R1 $0
      Exec $0
    FunctionEnd
    
    ; Check if XNA 2.0 or better is installed,
    ; will return $0 1 then, else $0 is 0.
    Function IsXNAInstalled
      Push $0
    
      ;Enumerate the versions installed.
      EnumRegKey $0 HKCU "SOFTWARE\Microsoft\XNA\Game Studio" "v2.0"
        ;if the root directory doesn't exist XNA is not installed
      StrCmp $0 "" notFound.XNA found.XNA
    
    notFound.XNA:
    ;MessageBox MB_OK "can't find XNA"
      StrCpy $0 0
      Goto done
    
    found.XNA:
    ;MessageBox MB_OK "found XNA or better"
      StrCpy $0 1
    
    done:
    ;MessageBox MB_OK "XNA found value: $0"
      StrCpy $R1 $0
      Exec $0
    FunctionEnd
    


  • And finally the uninstall section: This section will deinstall your game and get rid of all files in the directory that belong to the game, if there is more, it will not kill any other sub directories or even delete the game directory if there is other data present. If you want to be totally sure that only your game files are deleted, only include files that have been installed in this section via the Delete command. I used 2 RMDir /r commands to delete the Content and ColladaModels directories, which makes things much easier. But if for example the user made screenshots, they will be saved in a /Screenshots directory, which is not deleted here and will stay alive even after the uninstall is complete. There is also another check to make sure the game is still installed at this location by making sure the .exe file still exists. If the .exe file is missing, the uninstaller assumes the game is already uninstalled and it will only remove registry keys, but not any files.
    
    ; special uninstall section.
    Section "Uninstall"
      ; REMOVE UNINSTALLER
      Delete $INSTDIR\uninstall.exe
    
      ; remove registry keys
      DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\XnaSkinningColladaModels"
      DeleteRegKey HKLM "SOFTWARE\XnaSkinningColladaModels"
    
      ; remove shortcuts, if any.
      Delete "$SMPROGRAMS\XnaSkinningColladaModels\*.*"
      Delete "$DESKTOP\XnaSkinningColladaModels.lnk"
      ; remove directories used.
      RMDir "$SMPROGRAMS\XnaSkinningColladaModels"
    
      ; First check if rocket commander is located here, if not, dont kill stuff!
      IfFileExists "$INSTDIR\XnaSkinningColladaModels.exe" 0 RCNotFound
      ; remove files
      Delete "$INSTDIR\XnaSkinningColladaModels.*"
      RMDir /r "$INSTDIR\Content"
      RMDir /r "$INSTDIR\ColladaModels"
      
      ; Try to kill main folder, but this will fail if there are still some files in it
      RMDir "$INSTDIR"
      goto End
      RCNotFound:
      MessageBox MB_OK "XnaSkinningColladaModels.exe was not found in $INSTDIR, won't delete any files, $\r$\nplease remove directory and files yourself (all registry keys were killed)."
      End:
    SectionEnd
    

Okay, we have now covered all code of the XnaSkinningColladaModelsSetup.nsi file, download it and check it out for yourself if you want to learn more about it or even use it in your projects. Good luck!