sega 500 more nsis, the modern ui. jeff “ezeikeil” giles
DESCRIPTION
Today Now today came about as an attempt to kill two birds with one stone. As you may have noticed over the last 2 lessons, I’ve change how the content is delivered for this class. You now download an installer.TRANSCRIPT
Today
Since we’ve wrestled with the basics of the NSIS installers. Now we’re going to make them really useful and pretty.
Also we are going to expand our control over UT so that we can change it’s execution without mucking with UT’s core assets.
Today
Now today came about as an attempt to kill two birds with one stone.
As you may have noticed over the last 2 lessons, I’ve change how the content is delivered for this class.
You now download an installer.
Today
So were going to show you how I made this:
Why?
Well, yeah ya’ll know a fair bit about the NSIS installers now, but there is some real cleverness going on here.
If I do say so my self…
Why?
First off, it looks totally different… It’s using the modern UI (MUI) which allows us to customize it’s look.
You may have noticed the picture…
Why?
But not only that,
The text is completely customisable.
Why?
You can change the header templates
Why?
The title format in the menu bar.
Even the fonts and formatting.
Why?
Heck, even what the buttons say.
And if your feeling really ambitious, you can also change the layout of the windows by using different UI’s!
Why?
To top it off, it’s also possible to create your own UI’s and pages.
In effect creating a totally unique looking installer…
Why?
And as for the cleverness part, this installer is generalized to allow for “one-stop-shopping”.
In effect, with the changes to only a few parameters, I can create an complete installer for any one of my lessons very quickly.
Why?
Complete with registry entries and uninstaller.
An to top it off, I got it done in one evening.
As admission prices go... That’s not at all bad…
But first…
Before we dive into the big one, lets just start with a few simple MUI’s so that we can get our head around them.
So, Assuming your run the installer that comes with this lessons, you find Simple_MUI.nsi in the sample folder.
But first…
And the first thing to note is that we are customising the look of the installer, the functionality comes later.
But since we need to install something, the install section is simply:
But first…
This is the most uber, of uber simple installer, but it’s all we need to make it go.
And until we get to the big example, we’re not going to change this either.
OutFile "SimpleInstall_MUI.exe"InstallDir "$DESKTOP"
Section "INSTALLING STUFF"SetOutPath $INSTDIR
File "c:\Windows\notepad.exe"SectionEnd
Simple MUI
Ok, so getting this thing to use the MUI.
Well, it actually works in a similar manner to including a header file. You have to include System.nsh.
Simple MUI
Here’s the full declaration, just dump this at the top of the file.
!include command will include 'file' as if it was part of the
original script. Note that if a file is included in another directory, the current directory is still where the script was compiled from (not where the included file resides).
!include "${NSISDIR}\Contrib\Modern UI\System.nsh"
Simple MUI
And if you got impatient and ran it now, you’ll find that it looks exactly the same…no diff.
That’s because we are including macros! We still have to use them.
Simple MUI
So, we insert:
Which tells the NSIS to do just that, use the macro system.
Next we give it a macro to use.
!insertmacro MUI_SYSTEM
Simple MUI
Our first macro is the language file. We’ll talk about exactly what’s in here in a bit…
!include "${NSISDIR}\Contrib\Modern UI\System.nsh" !insertmacro MUI_LANGUAGE "English" !insertmacro MUI_SYSTEM
Simple MUI
And running it now gives: A custom MUI Icon
And a custom MUI window
Simple MUI
But do notice what’s in the window. Some weird ${MUI_ stuff
These are macros which get replaced automatically with our text.
Simple MUI
To do so is a simple call to define.
Add these to the very top of the NSI file so that the macro’s can seen them…once again, order counts.
!define MUI_PRODUCT "Modern UI Test Installer“!define MUI_VERSION "1.0"
Simple MUI
And there you go, you first MUI installer. Complete with product and version
information.
Adding Pages
The next thing to figure out is how to get the installer to have the multi pages that give us all that wonderful functionality…
You know, these fella’s.
Adding Pages
Welcome page
Licence page
Adding Pages
Component page
Install Location page
Adding Pages
Actually this is really easy. Each page is little more than a set of
macros. Hence you just select the pages you want from the list and add them to the nsi file.
Adding Pages
Here are the pages that Nullsoft provides for us. MUI_WELCOMEPAG MUI_LICENSEPAGE MUI_COMPONENTSPAGE MUI_DIRECTORYPAGE MUI_STARTMENUPAGE MUI_FINISHPAGE
Adding Pages
Most of these also have some sort of functionality that comes with them.
We’ll talk about those as the need occurs.
Adding Pages
Now, as I eluded to, using these is pretty simple. But they do have to be in a rather specific place.
In between:!include "${NSISDIR}\Contrib\Modern UI\System.nsh"
!insertmacro MUI_LANGUAGE "English" !insertmacro MUI_SYSTEM
Adding Pages
If not, it will not compile properly…if at all. To add the components page is as simple
as:!include "${NSISDIR}\Contrib\Modern UI\System.nsh"
!define MUI_COMPONENTSPAGE
!insertmacro MUI_LANGUAGE "English" !insertmacro MUI_SYSTEM
Adding Pages
Now when you run it…
Adding Pages
Now as you recall, the user can use this page to specify exactly what is installed onto their system.
This is done by giving your section a “name”. If it has one, it will automatically appear.
Adding Pages
We will talk some more about this later when we set up the rollovers for the description…
Yes…we can have rollovers too…Isn’t NSIS cool!
Section "INSTALLING STUFF"<SNIP>
SectionEnd
Editing Pages
For now, were sticking to customizing its contents look.
So, we now start to change the contents of the page…e.g. it’s text.
Editing Pages
Now, I know I’m going to repeat myself a fair bit today about the NSIS using macors…but really it is, and because it is, we can override them.
The same goes for all the text in the MUI’s. They all come out of a language marco file.
Editing Pages
If you crack open the NSIS director to the following path:
You’ll find the language macros. Crack the English one open, the text
should look awfully familiar.
\NSIS\Contrib\Modern UI\Language files
Editing Pages
Now before you start editing the contents of these nsh file…or creating your own for that matter…any one of these componets can be over ridden by using a !define.
Eg, for the title of the components page which currently reads "Choose Components“.
Editing Pages
In my installer script, I can simply add:
Which will over ride the default text. So long as its after the page declaration and before the MUI_LANGUAGE macro.
!define MUI_TEXT_COMPONENTS_TITLE "Pick'n choose"
Editing Pages
And as you can see the title text has changed.
You can do the same for any of the components listed in the language.nsh file.
Components Page Rollovers
Next, lets get that roll over working… When you place
the mouse over the component to install, it will change the contents of this window.
Components Page Rollovers
Now as mentioned, this is dependant on the sections.
And for simplicity, I’m just going to illustrate one.
Components Page Rollovers
So the first thing to grasp is that we need some sort of variable to get this to work.
Hence, just before the MUI_SYSTEM, we create one like so:
LangString DESC_Stuff ${LANG_ENGLISH} \ “The stuff we are installing."
Components Page Rollovers
In effect, this functions like a define, which we will use to substitute in our description string.
At which point we need to bind this to our section…Which is not exactly what you might expect.
Components Page Rollovers
The “Stuff” variable we will use to connect this section to our macro.
Section "INSTALLING STUFF" StuffSetOutPath $INSTDIR
File "c:\Windows\notepad.exe"SectionEnd
Components Page Rollovers
And finally, we use this to get the rollover working:
!insertmacro MUI_FUNCTIONS_DESCRIPTION_BEGIN !insertmacro MUI_DESCRIPTION_TEXT ${Stuff} $(DESC_Stuff) !insertmacro MUI_FUNCTIONS_DESCRIPTION_END
Components Page Rollovers
Now be sure to notice where these parameters are, AND that this marco is declared after all the sections.
MUI_DESCRIPTION_TEXT ${Stuff} $(DESC_Stuff)
Section Definition
Components Page Rollovers
When we run:
Our custom text appears in the description window when we move the mouse over the component.
Sweetness!
Components Page Rollovers
Just be aware that the modern3.exe UI does not have the roll over option.
Heh? What? modern3.exe? Huh?
Changing the Interface
OK, that came out of left field…what is it? You may have noticed that the format of my config screens are different…
Default MUI Modern2 UI
Changing the Interface
Well, you can use various UI exe files to tell the installer exactly what it looks like.
E.g. where to put the dialogues and the buttons and what not.
Changing the Interface
You’ll be able to find them here:
Just run some of these exe’s to get a feel for the look. The one I used in my installer is modern2.exe
\NSIS\Contrib\UIs
Changing the Interface
And getting your installer to use it, is once again, a simple define.
Yes, once again, this has to be above the MUI_SYSTEM.
!define MUI_UI "${NSISDIR}\Contrib\UIs\Modern2.exe"
Changing the Interface
Essentially, these exe files are nothing more than access methods for the resource components…which can be edited.
Thus further customising your interface.
Changing the Interface
Now I would have thought that you could access this via visual studio, but I had some problems with this.
However, there is a program called resource hacker which will allow you to access an change any of the installer resources.
Changing the Interface
Which you can get here:
Resource Hacker is a freeware utility to view, modify, rename, add, delete and extract resources in 32bit Windows executables and resource files (*.res). It incorporates an internal resource script compiler and decompiler and works on pretty much all windows operating systems.
http://www.users.on.net/johnson/resourcehacker/
Changing the Interface
It’s a very fun and powerful too, which you now have the option to play with…
My Pic
Next up, changing the Icons and pictures.
Both of which are one liners…
My Pic
Starting with the picture.
This is the default install picture that comes with the NSIS and it’s automatically presented with the “Welcome” and “Finish” screens.
My Pic
You’ll find this image, along with a pile of icons here:
Now, I’m fairly sure that the NSIS requires a reasonably specific format and size. But I have not found any documentation to this effect.
\NSIS\Contrib\Icons
My Pic
So I just grabbed the properties from this one and worked with in those parameter.
I did go for a larger bit depth though and it worked fine…Play around with it and see what you can get.
164w by 314h8 bit index colour
My Pic
Now, if your image exceeds these dimensions for width and height, I doubt it will cause much problem other than some cropping.
Ok, so getting the image in…the one liner.
My Pic
This is also a define which over rides the default setting of MUI_SPECIALBITMAP.
Yup, that’s it….and yeah… It also has to be above the MUI_SYSTEM call.
!define MUI_SPECIALBITMAP "EzeLogo.bmp"
My Icon
So next up is the icons, also found in the icons directory (duh!).
Now if you like you can create you own and use those if, it’s up to you.
But since the NSIS provides some really nice ones, I just opted to use those.
My Icon
One for the installer, one for the uninstaller.
And that’s that…
!define MUI_ICON "${NSISDIR}\Contrib\Icons\yi-box_install.ico"
!define MUI_UNICON "${NSISDIR}\Contrib\Icons\yi-box_UNinstall.ico"
Being Clever…
Next comes the bit I said about being clever in this things design.
What I did, using defines combined with my file structure, I created a sort of “one-stop-shopping” for my installer.
Being Clever…
That is to say, I place my NSI file in a root directory and by changing only one or two parameters, and specifying the files…by name only.
I can, in a matter of minutes, create an installer for a specific lesson…
And place the installer in the desired folder.
Being Clever…
So how did I go about doing this?
Well, right after the MUI_SYSTEM section, I simply created a set of defines for variables I knew I would use with each run.
These files were specific to my file structure.
Being Clever…
Just so you know what I’m talking about, on my home machine, I have in my root Lessons folder is whereI built the NSI file.
Along with various other things I needed for the installer…
Being Clever…
And have them all of the same naming convention.
E.g. Lesson, Lesson 2, Lesson 3… Lesson X…etc.
Being Clever…
The only exception to this is the private lessons where I have to change the path slightly to accommodate this.
Trust me…that’s no biggie.
Being Clever…
And then in my installer I create a few defines to reflect this…
!define LNUM 42
!define WORK_PATH "Lesson ${LNUM}"
Being Clever…
Using the LNUM define allows me to specify my lesson number in one place, and by reusing ${LNUM} as seen with the work path, I only ever have to specify my lesson number in one place.
As opposed to rewriting the path with each NSI script.
Being Clever…
And this allows me to use LNUM to specify my work path… e.g. where the NSIS will find my files that it will use to build the installer.
In effect, it concatenates the contents of LNUM (42 in this case) into a string which is then use to navigate into the target folder.
WORK_PATH "Lesson ${LNUM}"
Being Clever…
So when it comes time to grab a file, I can do something like this:
Where is grabs all the ppt’s out of the right file for installation.
Section "Install the lessons" Lessons
SetOutPath ${LESSON_PATH}File "${WORK_PATH}\*.ppt"
Being Clever…
Now, LESSON_PATH has a very similar purpose in life.
It is used so that anywhere I need to access the directory where I intend to install the lessons, I call it… Saving me the typing of the full path, numerous times.
!define LESSON_PATH $INSTDIR\Lesson${LNUM}
Being Clever…
If you look through the NSI script, you’ll see that I uses this same method for several items and even registry entries.
But to illustrate some of the payoff I get from doing this, look at how I output the installer.
Being Clever…
I never have to touch or edit this line again!
And every time. It I build an installer, it will output it into the correct work folder for me to upload and link to the HTML page.
OutFile "${WORK_PATH}\${LESSON_NUM}.exe"
Being Clever…
Also, when it comes to the uninstaller section, I never have to edit lines like these:
Delete "${LESSON_PATH}\Lesson ${LNUM}.ppt"
Delete "$INSTDIR\Uninstall_${LESSON_NUM}.exe"
RMDir ${LESSON_PATH} RMDir ${SAMPLE_PATH}
Being Clever…
Nor some of my registry entries…
DeleteRegValue HKLM ${REG_PATH} ${LESSON_NUM}DeleteRegValue HKLM ${REG_PATH} ${LESSON_PATH}
DeleteRegValue HKLM ${REG_PATH} ${SAMPLE_NUM}DeleteRegValue HKLM ${REG_PATH} ${SAMPLE_PATH}
Being Clever…
Thus with every NSI file, I set these in ONE place and I NEVER have to modify a fairly long list of instructions again.
It happens auto-magically.
Now is that sweet or what!
Ok
That’s a lot on the installers and the MUI.
Tomorrow we’ll wrap up a few odds and ends on the NSIS and talk about some optimizations and precaching of your Unreal scripts.