sega 500 more advanced nsis jeff “ezeikeil” giles jgiles@artschool.com jgiles

Post on 26-Dec-2015

219 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Sega 500

More Advanced

NSIS

Jeff “Ezeikeil” Gilesjgiles@artschool.comhttp://gamestudies.cdis.org/~jgiles

More on NSIS

As I eluded to last day, the NSIS is an insanely powerful.

To demonstrate that, we’re going to run with it some more and create some new NSI scripts that edit the registry, create uninstallers and edit ini files.

Adding Registry Entries

Thus, getting down to it, editing the Registry is the first step to creating an uninstaller.

In effect, we store some data in it which we can later access to find out what files we put where.

Adding Registry Entries

So first, a quick look at what the registry looks like.

You can access yours by typing regedit at the command prompt.

Adding Registry Entries

Registry keys Stored values

Adding Registry Entries

The NSIS gives us acronyms for accessing these:

HKCR or HKEY_CLASSES_ROOT HKLM or HKEY_LOCAL_MACHINE HKCU or HKEY_CURRENT_USER HKU or HKEY_USERS HKCC or HKEY_CURRENT_CONFIG HKDD or HKEY_DYN_DATA HKPD or HKEY_PERFORMANCE_DATA

Adding Registry Entries

Having a quick look we see that we can store all sorts of information in here.

My UT 2003 reg entry:

Adding Registry Entries

Now, you can edit this by hand if you like by right clicking the REF_SZ value, but this IS playing with fire... You will likely break stuff.

The registry is how windows know what, and where things are!

Adding Registry Entries

So what tools does NSIS give us then?

Well, if you refer to the docs, there’s a list of like a dozen items. We don’t need all of this functionality so we’ll just look at what we are going to use here.

Adding Registry Entries

InstallDirRegKey is the first item we need.

This attribute tells the installer to check a string in the registry, and use it for the install dir if that string is valid.

Adding Registry Entries

If this attribute is present, it will override the InstallDir attribute if the registry key is valid, otherwise it will fall back to the InstallDir default.

Adding Registry Entries

Usage:

InstallDirRegKey HKLM SOFTWARE\EZE_INSTALL "Install_Dir"

Registry path Value nameWhich key to install under

Adding Registry Entries

What this gives us…

A new registry directory under local machine

A variable to store our path in

Adding Registry Entries

HKLM: is HKEY_LOCAL_MACHINE key and we’ll be using this the most.

However, there’s no reason why you couldn’t store some of your data elsewhere.

Adding Registry Entries

SOFTWARE\EZE_INSTALL is literally the path in the registry (under HKLM) where to store our data

And the Install_Dir is the variable we create to hold out install path. It’s currently uninitalized.

Editing Registry Entries

Next we’ll need to set our value with WriteRegStr

Simply writes a string into the registry.

Notice the path and parameter is the same as above.

WriteRegStr HKLM SOFTWARE\EZE_INSTALL "Install_Dir" "$INSTDIR"

Editing Registry Entries

In this case, we store the path to our install directory.

WriteRegStr HKLM SOFTWARE\EZE_INSTALL "Install_Dir" "$INSTDIR"

Editing Registry Entries

So the next step towards building an uninstaller is to let the windows uninstaller know about it.

Editing Registry Entries

We achieve this by adding uninstall information into the windows uninstall registry.

SoftwareMicrosoftWindowsCurrentVersionUninstall

Editing Registry Entries

We simply use the same WriteRegStr command and specify a different path

WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Goober" "DisplayName" " EZE Installer (REMOVE ME)"

Editing Registry Entries

However in this case, we need to define our uninstall string also.

WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Goober" "UninstallString" '"$INSTDIR\uninstall.exe"'

Creating the Uninstaller

The actual creation of the uninstaller surprisingly simple…a one liner.

Where uninstall.exe is the desired name of the output uninstall program.

WriteUninstaller "uninstall.exe"

Creating the Uninstaller

Well, yeah, this will create the program for us, but it’s won’t do anything because we’ve not told it about where to get it’s uninstall information.

Creating the Uninstaller

Well, funnily enough, NSIS has commands for this too:

DeleteRegKey: Deletes a registry key. If “/ifempty” is

specified, the registry key will only be deleted if it has no subkeys (otherwise, the whole registry tree will be removed).

Creating the Uninstaller

So, in this case, we’ll need to specify DeleteRegKey command for both our dir and the windows uninstall dir.

Creating the Uninstaller

Notice the paths are the same as when we used the WriteRegStr.

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

DeleteRegKey HKLM SOFTWARE\EZE_INSTALL

Windows uninstall dir

Our Install registry entry

Creating the Uninstaller

And this will do just what it promises and remove the entries in the registry.

But what about the files? An uninstaller is no good if we don’t get ride of those!

Creating the Uninstaller

To simply delete a file is nothing more than: Delete $INSTDIR\Goober\Notepad.exe

Delete command: Delete file (which can be a file or wildcard, but

should be specified with a full path) from the target system.

Creating the Uninstaller

Hrmmm…”Wild card”?

Sure we can delete files one by one…But that’s lame. If we go back to the old DOS prompt days, we would use * operators to indicate “all”

Creating the Uninstaller

So if we go with the *.* we tell it the delete all files with any postfix

Will purge everything in this folder.

This also works for copying.

Delete $INSTDIR\Goober\*.*

Creating the Uninstaller

So then we just need to get ride of the uninstaller program and the directory.

Delete $INSTDIR\uninstall.exe

RMDir "$INSTDIR\Goober

Kill off the uninstaller

Remove the folder

Creating the Uninstaller

RMDir command: Remove the specified directory (which should

be a full path). Without /r, the directory will only be removed

if it is completely empty. If /r is specified, the directory will be removed

recursively, so all directories and files in the specified directory will be removed.

Creating the Uninstaller

So lets whip one up, and from there we’ll look at Editing ini files with NSIS

But this time, lets use something other than notepad to get started…

Slate Blue

I discovered this great scripting tool called Slate Blue which is super handy for setting up your nsi scripts.

There are 2 versions both available from http://www.morphedmedia.com/ …both are free.

Slate Blue

Version 1.0 is a really handy GUI for creating simple nsi scripts that can save you from the mundane tasks of setup…like name and color and what not.

Slate Blue

Then there’s version 1.07 which is a really nice scripting program which allows you to create and edit nsi scripts.

However, the last time I looked, it was a bit unstable.

Slate Blue

Not to mention that it has a full list of NSIS commands in the left window.

The right side is where you do your scripting…very handy.

Editing INI files

So on with INI files

Editing INI files

Once again, the actual editing of an existing ini file is surprisingly easy and NSIS have given us a nice tool to do it.

WriteINIStr Writes entry_name=value into [section_name]

of ini_filename. The error flag is set if the string could not be written to the ini file.

Editing INI files

In other words, this will seek a section head in a file and add an entry.

Eg, if I wanted to add an entry to section [public] in test.ini I could use

Editing INI files

WriteINIStr $INSTDIR\Goober\test.ini public "num1" "Something 1"

File name and full pathSection name[public]

Variable nameValue to be set

Editing INI files

Note: You can also use the WriteINIStr to create an ini file that is of the name in the path.

Editing INI files

OK, this is good and all, but there has to be some way to not have to enter ALL the ini edit commands into the installer…

’cause all that typing would suck.

Editing INI files

Rest easy, there is.

We can read from existing ini files using the ReadIniStr.

Editing INI files

ReadIniStr $1 "C:\...Folder\READtest.ini" Mo "num"

File name and full pathSection name[public] to read from

Variable name to readRegister in which to store the data

Editing INI files

Ok great, we can read from one file to another…one line at a time…still lots of typing involved in this.

But NSIS as you recall has piles of functionality with it. We can do string operations and even branching!

Editing INI files

So here’s what I have in mind. We’ll read data from an existing ini and store it in a variable.

We’ll then copy this data from the variable into the target ini file.

Loop until we reach the end of the read file.

Editing INI files

The data will be appended to the end of the test.ini file.

The only requirement in this case is that the variables in the read file must be named similar to num1, num2, num3…numX.

Editing INI files

Functionally, this is a really simple loop with a counter.

Editing INI files

Some functionality that we’ll need:

StrCpy Sets the user variable $x with str. Note that

str can contain other variables, or the user variable being set (concatenating strings this way is possible, etc).

Editing INI files

IntOp Combines value1 and (depending on OP)

value2 into the user variable $x Note: there’s a long list of operator that work

with this…consult the docs.

Editing INI files

StrCmp Compares (case insensitively) str1 to str2. If

str1 and str2 are equal, Gotos jump_if_equal, otherwise Gotos jump_if_not_equal.

Goto Being programmers, I’d be worried if you

didn’t know this one…Here’s the NSIS def:

Editing INI files

If label is specified, goto the label 'label_to_jump_to:'. If +offset or -offset is specified, jump is relative by

offset instructions. Goto +1 goes to the next instruction, Goto -1 goes to the previous instruction, etc.

If a user variable is specified, jumps to absolute address (generally you will want to get this value from a function like GetLabelAddress. Compiler flag commands and SectionIn aren't instructions so jumping over them has no effect.

Editing INI files

So, tying this together, we can start with this:

StrCpy $0 0

loop:IntOp $0 $0 + 1

Set register $0 to 0

Jump here if we loop

Increment by one…just like ++

Editing INI files

ReadIniStr $1 "C:\... Folder\READtest.ini" Mo "num$0"StrCmp $1 "" ExitLoop

Read in our data

Compare the stings.

If we read in nothing, it’s the end of the file so jump to the ExitLoop

Editing INI files

WriteINIStr $INSTDIR\Goober\test.ini Mo "Goob$0" "$1"

Goto loopExitloop:

Write our data to the new ini file

Jump to the loop case if we hit this

If we hit the exit loop, continue and exit. We’re done

Editing INI files

So lets give this a shot then we’ll move on to something a bit more funky with the ini editing.

More INI file control

Now for a little more power… The plan this time around is to directly access both files and copy only the first section out.

We’re only going the copy over the [Mo] section to the new file.

More INI file control

So what’s needed? Yup you guessed it, more commands.

More INI file control

FileOpen Opens a file named "filename", and sets the handle

output variable with the handle. The openmode should be one of "r" (read) "w" (write, all contents of file are destroyed) or "a" (append, meaning opened for both read and write, contents preserved).

In all open modes, the file pointer is placed at the beginning of the file.

If the file cannot be opened, the handle output is set to empty, and the error flag is set.

More INI file control

FileOpen $1 $INSTDIR\goober\test.ini w

Handle stored in register

Full path to file

Open method write (w)

More INI file control

FileRead Reads a string from a file opened with

FileOpen. The string is read until either a newline (or carriage return newline pair) occurs, or until a null byte is read, or until maxlen is met (if specified).

Strings are limited to 1024 characters. If the end of file is read and no more data is

available, the output string will be empty, and the error flag will be set.

More INI file control

FileRead $0 $2

Reads data from file handle $0 and stores it in register $2

More INI file control

FileWrite Writes a string to a file opened with FileOpen.

If an error occurs writing, the error flag will be set.

FileWrite $1 $2

Writes data from file handle $2 and stores it in register $1

More INI file control

FileClose Closes a file handle opened with FileOpen.

FileClose $0

Close the file with this handle $0

More INI file control

The program flow we’ll use here is the same as it was for the last example…

However, there are some differences in the usage of the StrCmp.

More INI file control

Since we are no longer looking for the end of file, the “” search key no longer works.

We need to search for *something*.

In this case “[meh]”

More INI file control

Now one would expect that simply plugging in “[meh]” would work…but it doesn’t.

The NSIS script reads the whole file. Including the non printing characters which is what gimps us.

More INI file control

This little item is not mentioned in the docs. I found the answer on the forums…after about 2 hours of twiddling with the NSI and searching.

More INI file control

In essence, we need to include the line feed and carriage return in the condition.

Or, no worky…

StrCmp $2 "[meh]$\r$\n" ExitLoopEND

More INI file control

There’s also one other neat little command that’s not mentioned in the docs which is DetailPrint.

This allows information to be displayed in the details window.

More INI file control

DetailPrint "$5 lines copied from READTest.ini to test.ini"

More INI file control

So our whole custom ini edit section will be something like:

Section "Playing with INI's"

;open out read write filesFileOpen $0 "C:\... Folder\READtest.ini" r ;read fromFileOpen $1 $INSTDIR\goober\test.ini w ;write to

;Our line counter set to 0Strcpy $5 0 ;

More INI file control

Loop:FileRead $0 $2 ;read a line into register 2

IntOp $5 $5 + 1 ; inc line counter

StrCmp $2 "[meh]$\r$\n" ExitLoopEND ; our exit conditionFileWrite $1 $2 ; write the line if I don't end

Goto Loop

More INI file control

ExitLoopEND:DetailPrint "$5 lines copied from READTest.ini to test.ini"

ExitLoop:;close the files...good house keeping.FileClose $0FileClose $1

SectionEnd ;

More INI file control

This conclude the presentation part for today.

And once again, we’ve not even scratched the surface of what the NSIS system can do…

Read the docs, visit the forums…make NSIS your friend!

top related