Archive: Install log useable by uninstall


Install log useable by uninstall
  I want to make a new sort of install log, in fact, in my main section, i use a command like that :

File /r "${PROJECT_PATH}\*.*"

This command include all files in ${PROJECT_PATH}, but the problem is the uninstall. I don't know what i've installed and if i've choose all the sections...

So that's why i want to know if somebody have ever made a install log system. i.e. you put all the files you've install in a .log, then the uninstaller read it and uninstall juste the files you've installed.

I've tried to do it but not succefully.

Thanks

PS: Sorry, i don't speak english very well :)


Why don't you put in in the registry?
Then write a macro wrapper around the File command which writes the file name to the registry before actually extracting the file.
Then all your installer needs to do is enumerate the values in the registry and delete those files.


Uninstalling Files
  Hola,

I am looking for a solution to the problem that TigerKnee is. In my case, I have around a thousand files to install to the users system. I don't want to clutter up their registry with that list.

In my case, the idea is to uninstall everything the installer put on the users system and only those files. Anyone have any ideas on a quick, reliable method to do so?


-V-


Put in a file the information (in a secure folder), as .INI files for example.


hola Deguix,

hmmm. That sounds like the best idea for now. I assume you are suggesting that I loop over the list during uninstall. That's what I intend to do.

Thank you for answering.


-V-


So instead of cluttering up the registry, you will clutter up the filesystem. Same difference.
[edit]Also consider that there is no built-in NSIS function to enumerate INI values. You will need write a function or macro to do it.[/edit]


It'll be easier to write to an ini file.
Just write to keys from 0 onwards, then on uninstall read from 0 and onwards.

-Stu


These are codes to remove files written in a INI File. Use this below in the installer, after every File command:

IntOp $R0 $R0+ 1

WriteINIStr "inifile.ini" "Installed Files" "$R0" "file.ext"
Where "file.ext" is the file want to be deleted in the uninstaller. You have to put too subfolder if is located inside a subfolder in installer folder. (i.e. Sound/Default/a.wav)

And "inifile.ini", the file used to store the name of files to delete in uninstall.

Use this below in the uninstaller (one time only):


ClearErrors


IntOp$1 $1 + 1
ReadINIStr$0 "inifile.ini" "Installed Files" "$1" "0"
>Delete "$INSTDIR/$0"

>IfErrors 0 -3
>
Where inifile.ini is the file used to store the name of files to be deleted.

Try it and say what is occuring using these codes.

Why is it easier to write/read from an INI file as opposed to the registry?
That's the bit I don't understand.


Hola,


The issue isn't whether one is easier than the other. The issue is whether it's appropriate or not.

One of the purposes of the registry is to store configuration settings for applications. I do this with many apps/components. However, in this case, I have several thousand files that are being installed on the user's system.

It would be asinine and criminal to put an entry in the registry for each file I am copying.

You compare cluttering up the registry with cluttering up the filesystem. Interesting.

By virtue of installing something on a target computer, one is 'cluttering up' the filesystem.

I can't remember the last time that an OS, as part of the boot process scanned and processed the entire filesystem, as is the case with the registry.

I do notice, however, that M$ has chosen (wisely) to retain Microsoft Installer related data in MSI files which reside on the users filesystem.

Whether the list of files is two or two thousand, it doesn't belong in the registry. There is no need for a list of files to be processed at boot time. There is more than likely no need for the application the installer is installing to have access to that data via the registry. Only during uninstallation, does it matter.

Putting the list of several thousand files in the registry requires that the uninstaller is used to remove the entries (which has the side effect of *uninstalling the application* or the user has to manually delete the registry entries. Storing it in a file in the $INSTDIR or $INSTDIR\Uninstall allows the user to remove or move the log file if they feel the need to do so. This does, however, that the SuperPimp (the person creating the installer using NSIS) write functions in such a way that uninstallation can continue if the log file is unavailable. I would much rather give the user an option than putting even more unrequired data in the users registry.

Lastly, as you can see by the example deguix provided, using a log file is a quick and easy thing to do which has two benefits and a side effect which is easily compensated for with a little thought.

I am not suggesting that the registry shouldn't be used. It's there to be used and the purpose of the registry is a good one. By all means, use it. Use it for application configuration, use it for file associations, use it for component registration. But don't use it just because it's there.


-V-


The issue isn't whether one is easier than the other. The issue is whether it's appropriate or not.
I don't dispute that. I was replying to Afrow UK who said it is easier to put it in an INI file. In terms of pure programming and/or performance, I don't see that as being necessarily true.

It would be asinine and criminal to put an entry in the registry for each file I am copying.
Criminal? Isn't that a bit harsh?

You compare cluttering up the registry with cluttering up the filesystem.
What I intended to say is that, one way or the other, you are putting some additional information/metadata on the user's computer- instead of putting it in the registry, you are putting it in the filesystem.

I can't remember the last time that an OS, as part of the boot process scanned and processed the entire filesystem, as is the case with the registry.
Does the registry scan the whole filesystem upon boot? I don't think so.

I do notice, however, that M$ has chosen (wisely) to retain Microsoft Installer related data in MSI files which reside on the users filesystem.
An MSI file is simply a Windows Installer database. Consider it analogous to an .nsi file.

Putting the list of several thousand files in the registry requires that the uninstaller is used to remove the entries (which has the side effect of *uninstalling the application* or the user has to manually delete the registry entries. Storing it in a file in the $INSTDIR or $INSTDIR\Uninstall allows the user to remove or move the log file if they feel the need to do so. This does, however, that the SuperPimp (the person creating the installer using NSIS) write functions in such a way that uninstallation can continue if the log file is unavailable. I would much rather give the user an option than putting even more unrequired data in the users registry.
Couldn't everything you said in favor of the INI file be applicable to the registry as well.

I am not suggesting that the registry shouldn't be used. It's there to be used and the purpose of the registry is a good one. By all means, use it. Use it for application configuration, use it for file associations, use it for component registration. But don't use it just because it's there
I thought it was there to get away from the INI file hell created by Win 3.x

When all is said and done, you do what works best for you.
You prefer using an INI file, more power to you.

Yeah, but i used just one File command to include all my files, that's why i can't write in a .ini each time a file is added. I've tried to add my files one by one, but it's a little bit annoying.

Instead of a macro or something else, i just want to know if we can make hooks of NSIS functions, it should be great if each time the File function is called (or a other function), NSIS call your own function too. It should solve a lot of problems. Maybe in a future version ;)

Else i'll use a macro :)


Originally posted by tigerknee
Instead of a macro or something else, i just want to know if we can make hooks of NSIS functions, it should be great if each time the File function is called (or a other function), NSIS call your own function too. It should solve a lot of problems. Maybe in a future version ;)
Exactly what I was thinking :)

Alas, it'll have to wait.

INI file is not easier or hard than registry. Depend what want and prefer, i.e. is better put the Install Dir in registry than put in a file, but put texts and more texts in a ini file is better than registry. You can do by those two ways, it is up to you.


I would myself use an ini file to store the uninstall data.
Now, instead of having to manually write all the files from the directory into my nsis script to compress, I'd simply write another nsis installer (program) that used FindFirst, FindNext, FindClose to get all the file names in my directory to compress, then write them to a file (using FileOpen, FileWrite) to generate the nsis script for me.

-Stu


You don't even need to do that. A simple windows batch file can do the trick for you (i.e., generate the nsis script).
I am using batch files along with the !system precompiler command to do dynamic file discovery while building my scripts. The batch files generate *.nsh files which are included in my main *.nsi script.


a little confused
  Sorry to intrude, but as i'm having similar 'issues', I was interested in this thread...however, it started getting strangely complicated.

I would have thought that a little bit of planning of the install was all it takes, but maybe i'm missing something:

If you have 5 sections (for example), each section writes a single Registry entry (saying "hey! i've been installed") indicating that it's been installed.

On uninstall, it reads these registry entries, if it finds it, reverses the 'install' process, and deletes the entry.

Each section can have a million files, but you only get a single reg entry per section (I wrote a little utility that allows you to right click on a folder and it'll display a list of 'file ...' and 'delete ...' entries to paste into the .nsi file, when there are huge quantities of files to copy, well, more than 5, anyway :) )

Really, all you need to store in the registry are the 'user' selections - (i.e. a section is either installed, or it's not). You don't need an 'entry per file'.

Does this make sense? Or am I missing a 'feature' somewhere? (Hope not, because i've just deployed several installs doing this :eek: )

SteelCoder


Re: a little confused
 

Originally posted by SteelCoder
Sorry to intrude, but as i'm having similar 'issues', I was interested in this thread...however, it started getting strangely complicated.

I would have thought that a little bit of planning of the install was all it takes, but maybe i'm missing something:

If you have 5 sections (for example), each section writes a single Registry entry (saying "hey! i've been installed") indicating that it's been installed.

On uninstall, it reads these registry entries, if it finds it, reverses the 'install' process, and deletes the entry.

Each section can have a million files, but you only get a single reg entry per section (I wrote a little utility that allows you to right click on a folder and it'll display a list of 'file ...' and 'delete ...' entries to paste into the .nsi file, when there are huge quantities of files to copy, well, more than 5, anyway :) )

Really, all you need to store in the registry are the 'user' selections - (i.e. a section is either installed, or it's not). You don't need an 'entry per file'.

Does this make sense? Or am I missing a 'feature' somewhere? (Hope not, because i've just deployed several installs doing this :eek: )

SteelCoder
For most cases that should work fine. It really depends on what files you install and where you install them. In the original post, he said he didn't know the file names. Perhaps he was installing some files to the $WINDIR. In that case, he couldn't just say RMDIR /r $WINDIR on uninstall, so knowing the files you install would be extremely important in that case. Of course, I usually find it best to add all files explicitly (perhaps requiring some preprocessing of your directory to do this). This will help assure better quality control on uninstall.

Not confused any more
 

Originally posted by rainwater
<snip>...
In the original post, he said he didn't know the file names.
...<snip>
Arrg...missed that. That's why I went to explicitly declaring each and every file - got into trouble with the File "*.*"...I knew I did it for some reason! :D

SteelCoder
(note to self: read threads thoroughly)

I'm currently fiddling with NSIS and trying various things. One of the problems I'm dealing with is as above, how do you delete only things that the user had installed? The following are 3 pieces of test code which are meant to address this problem. It's good code; the only problem is that it doesn't work, and I'm not sure why.

(It's a moderately complex sample, and documented, so it's unfortunately long.)

[edited by kichik]attach large scripts. attached below.[/edit]


The first problem I see is that you don't seem to saving the final flag string ($R9) anywhere. So when your uninstaller starts, $R9 is a blank string- so obviously it fails. What you need to do is save the value of $R9 in the registry. Then read it back into $R9 at the beginning of your uninstall section.
There may be other problems- this is most obvious one that jumps out.
[edit]One more thing- I see a lot of code duplication. You might want to consider writing a couple of macros. For example, the SetFlag & GetFlag nsh files could simply be made into macros. That way you don't have those multiple !include directives.
Also, you have way too many RmDir commands in your uninstaller. Read the RmDir documentation- you can probably reduce this number to just 6 or 7.[/edit]


.


Iceman_k:

Thank you for your response. Your response, however, indicates that I'm misunderstanding how some of this stuff works. My understanding is as follows:

I build a script. I then invoke the compiler to convert the script to an EXE. I run the EXE. At the start of the EXE, R9 is, of course, empty. It hits the initialization section, and R9 gets set to NNNNNN. I go through the selection procedure, indicating what I want installed (we'll assume that I *don't* want COMP installed). The EXE runs through the various installation sections, modding R9 as it goes. When it reaches the end of the installation sections, R9 is set to YYYYNY. It then continues on into the section where it constructs the uninstaller executable. At this point, R9 should still be set. It should then be using the contents of R9 to selectively write in the deletion orders, in this case skipping over the orders related to deleting the COMP file(s). The end result should be an uninstall EXE with commands that delete everything except those related to COMP. The uninstall should have been built with the content of R9 in mind, without needing to save R9 anywhere.

Judging by your response, however, the above is wrong. How so?

Also, regarding your suggestion to put the content of R9 in the Registry, this has been ruled out by my superiors. They require that all of my scripting actions do not touch the Registry as the user may not have Administrator privileges (yes, this will probably give me grief when it comes to installing other packages via this script). As an alternative, I suppose I can write R9 to a file and read it back in later. I'm going to be doing some reading with that in mind. I still don't, however, see why R9 must be saved. As I described above, I thought R9 would be immediately used in the design / construction of the uninstall executable.

In re using macros, that's later on my to-do list. First, I'm just trying to figure out the various bits of the scripting language (which I'm short on, based on the above).

In re RMDir, yes, I forgot about /r.

Kichik:

Thank you for modding my earlier code samples into an attachment. I've looked over this page, though, and I don't see how I can, umm, attach an attachment. (I don't use message boards very often.) Do I do it by simply dumping the material onto a web page then provide a URL link to it?

Botheration. System decided I wasn't logged in anymore, had to rewrite this entire message. Hope I didn't miss anything.


In the quick reply box you don't have an attachment box, but when click on the Post a Reply button, you do.


I build a script. I then invoke the compiler to convert the script to an EXE. I run the EXE. At the start of the EXE, R9 is, of course, empty. It hits the initialization section, and R9 gets set to NNNNNN. I go through the selection procedure, indicating what I want installed (we'll assume that I *don't* want COMP installed). The EXE runs through the various installation sections, modding R9 as it goes. When it reaches the end of the installation sections, R9 is set to YYYYNY. It then continues on into the section where it constructs the uninstaller executable. At this point, R9 should still be set. It should then be using the contents of R9 to selectively write in the deletion orders, in this case skipping over the orders related to deleting the COMP file(s). The end result should be an uninstall EXE with commands that delete everything except those related to COMP. The uninstall should have been built with the content of R9 in mind, without needing to save R9 anywhere.

Judging by your response, however, the above is wrong. How so?
Yes it is wrong. All the actions you describe above are runtime actions. The uninstall section is part of the the uninstaller executable. So it does not get invoked during installation. Similarly none of the installation sections get invoked during uninstallation. There is no direct communication between installer and uninstaller exes. You need to build that communication using the registry or an INI file.
The uninstaller is not dynamically compiled and built. Its structure is predetermined no matter what your installer does. This is the same for any installation product out there.

Also, regarding your suggestion to put the content of R9 in the Registry, this has been ruled out by my superiors. They require that all of my scripting actions do not touch the Registry as the user may not have Administrator privileges (yes, this will probably give me grief when it comes to installing other packages via this script). As an alternative, I suppose I can write R9 to a file and read it back in later.
Write it to an INI file in your install directory. Then read it back when you start your uninstaller.