Creating a windows application

On Windows computers, applications aren't really more than the executable. Here I will show you how I created the Windows installer for one of my C++ projects. In my project, I used the GTK+3.0 library. I will not explain how to link a library, but you do need to do some things when using a library. Make sure the library is linked correctly!

NOTE: eventhough I did successfully created the app, I learned how to do it by reading bits and pieces here and there and cannot tell if this is the best way.

The first thing is to create your executable, this process varies per language and IDE. My app is written in C++ and compiled with MSYS and the MINGW compiler. If you are using Visual Studio, don't forget to set the solution configuration to "Release".

I found it easier to have a folder on my desktop and work from there, so I created a folder and dragged my executable from the Release folder into that folder. The next step, is to find the dependencies your executable has. You might know exactly which dependencies your program has, but I like to be sure and make things easy for myself. I use Dependency walker, this software lists all dependencies and the path to the dll file. In my dekstop folder, I created a subfolder called dll and put all the dll's that my program needs in that folder.

When copying the dll's, make sure you are using the exact file you need. There are 32-bit and 64-bit dll's and sometimes the names are really similar. If you use a 32-bit dll in a 64-bit program (or vise versa), the program will not start. There are also a couple of Windows dll's where your application will depend on. these dll's are installed on every Windows machine, but the versions may vary. It is possible your app depends on certain functionalities which are added in later versions of the dll. If someone is not up-to-date with the dll's, the app will not work.

The sequel Windows searches for dll's is as following:

  1. The directory where the executable module for the current process is located.
  2. The current directory.
  3. The Windows system directory. The GetSystemDirectory function retrieves the path of this directory.
  4. The Windows directory. The GetWindowsDirectory function retrieves the path of this directory.
  5. The directories listed in the PATH environment variable.

There are many things that can (and will) go wrong with the dll's and the application, which causes the application to work on most computers, but not on all. This is know to developers as DLL hell, more information about that can be found on this wiki. Make sure you are actually copying the dll's and not moving them!

After the rage inducing task of getting the correct dll files, I created another sub folder in my desktop folder called `Resources`. In this folder I put all my resources, like json files, images, stylesheets.

Everything your program needs is now in one spot and we can start on the installer. I used NSIS to create my installer, which is available on their main page.

The installer is going to be really basic and will include the following pages:

In the desktop folder, create a file with the nsi extension (I called it installer.nsi). Open it with your favourite texteditor and start off with the following sample code (Lines starting with a `#` are comments):

#This is the name of your program
Name "MyProgram"
#Here, you set the default installation folder, usually the program files folder
InstallDir $PROGRAMFILES
#Here you define what the name of the installer will be
OutFile "My-App-Installer.exe"

#include the ui library
!include "MUI2.nsh"

#Set an icon for the intaller (must be a .ico image)
!define MUI_ICON "Path\To\My\image.ico"

#Welcome page
#The fat title at the top of your welcome page
!define MUI_WELCOMEPAGE_TITLE  "Install my app"
#The text on the welcome page
!define MUI_WELOMEPAGE_TEXT "Thank you for installing my app! Please follow the instructions."
#The image on the left of the installer (not required! Only accepts valid bitmaps!)
!define MUI_WELCOMEFINISHPAGE_BITMAP "Path\To\My\Image.bmp"
#Create the page
!insertmacro MUI_PAGE_WELCOME

#Licence page
#Title
!define MUI_PAGE_HEADER_TEXT "Licence Agreement"
#Subtitle
!define MUI_PAGE_HEADER_SUBTEXT = "Please review this Licence Agreement before installing My App"
#Text above licence
!define MUI_LICENSEPAGE_TEXT_TOP "Press Page Down to read the rest of the agreement"
#Text below agreement
!define MUI_LICENSEPAGE_TEXT_BOTTOM "If you accept the terms of agreement, click the checkbox and continue the intallation"
#Create the agree checkbox
!define MUI_LICENSEPAGE_CHECKBOX
#Set the label of the checkbox
!define MUI_LICENSEPAGE_CHECKBOX_TEXT "I have read and agree with the Terms and Conditions"
#Set accept button label
!define MUI_LICENSEPAGE_RADIOBUTTONS_TEXT_ACCEPT "Continue"
#Create licence page, the argument is the path to a txt file that holds the terms and conditions
!insertmacro MUI_PAGE_LICENSE "Path\To\My\Licence.txt"

#Installation directory
#Text on top of page
!define MUI_DIRECTORYPAGE_TEXT_TOP "Select insatllation folder"
#Text above the path display
!define MUI_DIRECTORYPAGE_TEXT_DESTINATION "Destination:"
#Add page
!insertMacro MUI_PAGE_DIRECTORY

#Install page
!insermacro MUI_PAGE_INSTFILES

#Here we set what files are installed where.
Section "instfiles"
  #Set the pathto the install directory
  SetOutPath $INSTDIR\MyApp

  #Here we locate the executable relative to the nsi script.
  #I put the nsi sript in the same folder as my executable
  File MyExecutable.exe
  #Create a shortcut on the desktop
  CreateShortCut "$DESKTOP\MyAppName.lnk" "$INSTDIR\MyApp\MyExecutable.exe" ""

  #Now we load all the dll files relative to the installer script. I put my dll's in the dll folder
  File dll\SomeDLL.dll
  File dll\GUI-THING.dll
  File dll\PLEASE_WORK.dll

  #Now it's time for the resources. This needs to be put in the folders you used in your code.
  #If your code says: `auto myImage = LoadResource("images/myImage.png")` then your image needs to be located in the images folder.
  #I like to put all my resources in a resources folder and create subfolders if needed.

  #Update the output folder to be the resources folder
  SetOutPath $INSTDIR\MyApp\resources
  #Set the resources relative from the installer script
  File resources\info.json
  File resources\stylesheet.css
  #Update the output folder
  SetOutPath $INSTDIR\MyApp\resources\images
  File resources\logo.png
  File resources\header.jpg

  #Create an uninstaller
  WriteUninstaller $INSTDIR\MyApp\uninstaller.exe
SectionEnd

#Finish page
!define MUI_FINISHPAGE_TITLE "MyApp is successfully installed"
!insertmacro MUI_PAGE_FINISH

#Set uninstall logic
Section "Uninstall"
  #Always delete the uninstaller first
  Delete $INSTDIR\uninstaller.exe
  Delete $INSTDIR\MyExecutable.exe

  Delete $INSTDIR\SomeDLL.dll
  Delete $INSTDIR\GUI-THING.dll
  Delete $INSTDIR\PLEASE_WORK.dll

  Delete $INSTDIR\resources\info.json
  Delete $INSTDIR\resources\stylesheet.css
  Delete $INSTDIR\resources\images\logo.png
  Delete $INSTDIR\resources\images\header.jpg

  RMDir $INSTDIR\resources\images
  RMDir $INSTDIR\resources
  RMDir $INSTDIR
SectionEnd

#Set language, may throw errors if langauage is not set
!insertmacro MUI_LANGUAGE "English"

Open NSIS, click on compile script and drag your nsi script on the window. Wait for it to compile and correct any errors you might get. The installer will be created in the folder where then installer script is located and is ready to use.