Archive: Advanced Uninstall Log NSIS header


Advanced Uninstall Log NSIS header
Advanced Uninstall Log is a macro system provided in a NSIS header that
is able to monitor an installation and build an uninstall log file which
is used by the uninstaller to uninstall files/directories that have been
added within specific installation blocks.

This means that files which have been installed outside these blocks,
or added later either by the user or application's activities, ignored
by the uninstaller.

Moreover files that might exist into the target directory prior the current
installation, ignored as well.

More informations and download links including 2 detailed examples of usage, at wiki:

http://nsis.sf.net/Advanced_Uninstall_Log_NSIS_Header


Cool, Red Wine. My suggestion is to enable multilanguage support for the messages.


Originally posted by zeeh3
Cool, Red Wine. My suggestion is to enable multilanguage support for the messages.
Thanks! I'm a bit dry of ideas on how to enable multilingual support and keep the high automation of the header at the same time, I'm tended to implement the same technique that I've implemented here , but I'd like to wait a little for a possible better suggestion.

you definetly should wait for nsis 2.24, where a whole bunch of preprocessor enhancements will make life easier :)

btw: this lib looks nice!


Originally posted by Comm@nder21
you definetly should wait for nsis 2.24, where a whole bunch of preprocessor enhancements will make life easier :)

btw: this lib looks nice!
It is true that I never claim that I know the inner works of the development team, yet I'm unable to figure how the 2.24 release would make my life easier according to enable multilingual support for 4 message boxes.

Thanks for writing this header Red Wine!

I needed to be able to localize the messages boxes it shows, so I made some modifications.

If you don't need to make any localizations it will work just as it did before. But if you do need to change the strings it shows this is the way to do it with my version:

!define UNINSTALLOG_LOCALIZE ;if you define this you have to provide language strings to use

LangString UNLOG_HEADER ${LANG_ENGLISH} "=========== Uninstaller Log please do not edit this file ==========="
LangString UNLOG_DAT_NOT_FOUND ${LANG_ENGLISH} "${UNINST_DAT} not found, unable to perform uninstall."
LangString UNLOG_DEL_FILE ${LANG_ENGLISH} 'Delete File "$R9"?'
LangString UNLOG_DEL_DIR ${LANG_ENGLISH} 'Delete Directory "$R9"?'
LangString UNLOG_EMPTY_DIR ${LANG_ENGLISH} "Previous installation detected at $0.$\nRequired file ${UNINSTALL_LOG}.dat is missing.$\n$\nIt is highly recommended to select an empty directory and perform a fresh installation."
LangString UNLOG_ERROR_LOG ${LANG_ENGLISH} "Error in log ${UNINSTALL_LOG}."
LangString UNLOG_ERROR_CREATE ${LANG_ENGLISH} "Error creating ${UNINSTALL_LOG}."


If UNINSTALLOG_LOCALIZE isn't defined the english language strings above will be used.

This is the full header after my modifications:
http://pastebin.com/f8fa1474

Nice job TobbeSweden :)

You may want to add your modified header in wiki as well.


Done. http://nsis.sourceforge.net/Advanced_Uninstall_Log_NSIS_Header#Modifications

Feel free to edit/move anything you like


Hi!

I ran into a problem with the example script ""Advanced Uninstall Log Demo". At uninstall there was a problem with removing empty directories. The code below prevented the uninstaller from hanging, but the real solution was to upgrade from Nsis 2.10 to Nsis 3.3 :) which solved the problem!


!macro UNINSTALL.LOG_UNINSTALL_UNATTENDED
Function un._LocateCallBack_Function_Unattended
....

isdir:
RmDir "$R9"
IfErrors +1 isdir2
MessageBox MB_ICONEXCLAMATION|MB_OK "Could not remove directory $R9" /SD IDOK
goto end
isdir2:
IntOp $unlog_tmp_1 $unlog_tmp_1 + 1
goto end


I was going to ask for help, but this turned into an advice for people having similar problems with RmDir: Upgrade Nsis!

Thanks for the script Red Wine! Though I would have liked some more comments in the source code... (AdvUninstLog.nsh)

Best regards
/Henrik

Unicode version
Hey, Red Wine. First, I want to say thanks for your header - it should come with NSIS by default, if you ask me.
And now, the question... The header is working with experimental version of unicode NSIS, but it produces an ANSI file etc. - would it take much to create a version which is working properly with unicode? A lot of changes or ...?


Re: Unicode version

Originally posted by high1
Hey, Red Wine. First, I want to say thanks for your header - it should come with NSIS by default, if you ask me.
And now, the question... The header is working with experimental version of unicode NSIS, but it produces an ANSI file etc. - would it take much to create a version which is working properly with unicode? A lot of changes or ...?
Hey, high1, thanks for your comments!
Feel free to modify it the way it suits your preferences and don't forget to contribute at wiki please :)

Happy new year!

With some tinkering and a lot of help from Jim who is responsible for the NSIS Unicode patch, I got the header working. Modifying the header is trivial, and includes replacing FileRead and FileWrite calls with FileReadUTF16LE and FileWriteUTF16LE. You also need to write a BOM at the begging of the file to make it unicode. But the header uses FileJoin macro from TextFunc header, and it can not deal with unicode files, so I had to replace the call for FileJoin with a custom macro inside the header - FileJoinUTF. It is a modification of FileJoin and all the credits go to it's author. Here is the patched header :


Thank you for the header. Looks good. Does anyone tryed it with the add / remove features section in installer?


Please tell me how to customize uninstall program's directory and name using this header?

And is there someone who can explain me when these error messages appear? :)


Just want to ask, what if i only want to pop-up the dialog that is only for directory excluding for the files pop-up dialog using this AdvUninstLog.nsh. thanks


Originally posted by sphynx07
Just want to ask, what if i only want to pop-up the dialog that is only for directory excluding for the files pop-up dialog using this AdvUninstLog.nsh. thanks
You'd need to edit header's code...

Thanks Red Wine.
I tried it but for no luck i could not get it. sigh...
What i wanted to do with my uninstaller is that, the message box detection for newly created folder/directory will only pop up ignoring the files inside it and once the user wants to delete the folder the uninstaller will then also automatically delete the file/s inside it.
Can you please help me on this.
Please advice...

Thanks!


I understand what you're trying to achieve though as I suggested above you'd need to work with the existing code or write a new one.


Hi all,

i have (as usual) a little problem.

Even though all the necessary files are recorded in uninstall.dat they are not removed completely.

I have a folder $InstDir\bin that is only partially emptied even though all files are recorded and should have been removed.

Is there a way to log what gets deleted and what not (and maybe why?).

The $InstDir\bin folder gets filled by different sections in between which other folders get created and filled. All other folders get removed nicely only bin stays (with quite a lot of files). Once i changed the Uninstall.dat to only contain the files that are in \bin and it worked nice, later i tried sorting so all \bin files are together in one section instead of being distributed over the uninstall.dat but that did not work either. I also tried to find out if those files are special in any way like special characters or so, but nope i couldn't find anything.

Right at the beginning when i started implementing it it seemed to work nice, only a couple files were left but now....

Strange but its late and i guess i can't think right either, any help is appreciated.

Thanks for reading :)


Are the files in use when you try to delete them? Since you're talking about a bin directory, maybe the program you're trying to delete is still running?


Well there might be one or two files still in use, but there are well over 100 left that do not get deleted.


Hello,

I have a problem and I hope you can help me.

My Problem is that the uninstall-process is to slow, can
I do something to speed it up.

regards
cool-zer0


Most likely it is due to the mentioned disadvantage of the header (especially noticeable when dealing with too many files on old-slower machines) which needs some effort to eliminate it.

http://nsis.sourceforge.net/Advanced...r#Disadvantage


Since latest version of Unicode NSIS is able to parse an ansi script as unicode (doesn't need to convert the script prior to compile), I merged the above patch from high1 in one multi-functional header.

This means there's only one header (which itself is ansi), who's able to utilize both NSIS flavors hence produce ansi or unicode uninstall.dat respectively.


Hi Red Wine,

Thanks for coding up this header. Its definitely a great addition to an already excellent product.

However I am also having issues with the speed of the uninstall. I am uninstalling about 50mbs of an applicaiton which includes up to 2000 files.

Do you think this header is just not suited to the characteristics of my application. Alternatively is there any code that I can change in the header file myself that might speed up the uninstall.

BTW I am using the Unicode NSIS branch and I have used your latest script attached in this thread.

Thanks for your help in advance.


It IS really an excellent header, and same with jr_spurs, i as well am having problems with the speed of uninstalling...

You're having difficulty with 50 mb? i have a 4gb++ installation to handle xD

The uninstaller has been running for close to 2 hours now, and its still nowhere near done hahaha

It would be nice if something could be done to speed this up...


From my own experiments it seems only files added inside $INSTDIR get removed. During my install process I install files in many different places, but only the ones in $INSTDIR get removed during uninstall even though all "File ..." calls are wrapped in the required UNINSTALL.LOG... macros. Is this normal/correct?


i'm not pro at NSIS, but did you check Uninstall.dat in INSTDIR post install to make sure that the directories were logged correctly?

From what i can tell about the script, there shouldn't be limitations in install directories differing from INSTDIR


File capture
I am trying to understand this script as I am relatively new to NSIS. There seems to be some "magic" happening here that I am trying to understand.

Before capturing files, you insert the macro "UNINSTALL.LOG_OPEN_INSTALL". Then call your "File [options] [folder]". The macro contains "${uninstall.log_install} "${EXCLU_LIST}" "${UNINST_DAT}" "$OUTDIR"".

Exactly what I am trying to figure out is how all this work? How does the code in the macro get the information it needs?

Is it that NSIS creates the "exclude.tmp" file in the $PLUGINSDIR, when using the "File" command, and this script then leverages it?


Uninstaller details
Hi guys,

I am encountering the following issue. The Uninstaller details list is empty when executing the uninstaller. I have set ShowUninstDetails show but the list only displays the shortcut and installation folder deletion.

Is there any reason for this behavior?
I'm missing something maybe?

Best regards,
Isawen


Re: Uninstaller details

Originally posted by isawen
Hi guys,

I am encountering the following issue. The Uninstaller details list is empty when executing the uninstaller. I have set ShowUninstDetails show but the list only displays the shortcut and installation folder deletion.

Is there any reason for this behavior?
I'm missing something maybe?

Best regards,
Isawen
I've figured out the solution and you could see it at the following address: http://forums.winamp.com/showthread.php?postid=2625204#post2625204

Hope this will be usefull for somebody.

Originally posted by HaMsTeYr
It IS really an excellent header, and same with jr_spurs, i as well am having problems with the speed of uninstalling...

You're having difficulty with 50 mb? i have a 4gb++ installation to handle xD

The uninstaller has been running for close to 2 hours now, and its still nowhere near done hahaha

It would be nice if something could be done to speed this up...
Yes .. the uninstall log is great but extremely slow when uninstalling large numbers of files. Have any way to speed it up? :)

Originally posted by dorakey
Yes .. the uninstall log is great but extremely slow when uninstalling large numbers of files. Have any way to speed it up? :)
On that note, and since this is an old thread, yes, yes i do have a way to speed it up. I actually went in and rewrote the code into something a lot simpler, and so far i've not encountered any major problems with it.

Its just a makeshift rewriting though, but if you're interested in it i can upload it.

Originally posted by HaMsTeYr
On that note, and since this is an old thread, yes, yes i do have a way to speed it up. I actually went in and rewrote the code into something a lot simpler, and so far i've not encountered any major problems with it.

Its just a makeshift rewriting though, but if you're interested in it i can upload it.
Yes, please do upload it, thanks ! :up:

Here it is, to use it:
Add
!include AdvUninstLog2.nsh

and since its a very makeshift modification, you can only use these macros

!insertmacro UNATTENDED_UNINSTALL

Section ""
!insertmacro UNINSTALL.LOG_OPEN_INSTALL
File "SomeFile"
!insertmacro UNINSTALL.LOG_CLOSE_INSTALL
SectionEnd

Function .onInit
!insertmacro UNINSTALL.LOG_PREPARE_INSTALL
FunctionEnd

Function .onInstSuccess
!insertmacro UNINSTALL.LOG_UPDATE_INSTALL
FunctionEnd

Section "Uninstall"
!insertmacro UNINSTALL.NEW_UNINSTALL "$OUTDIR"
SectionEnd

For the uninstall section, i don't think the OUTDIR should matter much as i've coded it such that it looks for the whole directory from the root drive.

Anyway, those are the ones i'm using at the moment and they work well for me. Give them a shot :)


Originally posted by HaMsTeYr
Here it is, to use it:
Add
!include AdvUninstLog2.nsh

and since its a very makeshift modification, you can only use these macros

!insertmacro UNATTENDED_UNINSTALL

Section ""
!insertmacro UNINSTALL.LOG_OPEN_INSTALL
File "SomeFile"
!insertmacro UNINSTALL.LOG_CLOSE_INSTALL
SectionEnd

Function .onInit
!insertmacro UNINSTALL.LOG_PREPARE_INSTALL
FunctionEnd

Function .onInstSuccess
!insertmacro UNINSTALL.LOG_UPDATE_INSTALL
FunctionEnd

Section "Uninstall"
!insertmacro UNINSTALL.NEW_UNINSTALL "$OUTDIR"
SectionEnd

For the uninstall section, i don't think the OUTDIR should matter much as i've coded it such that it looks for the whole directory from the root drive.

Anyway, those are the ones i'm using at the moment and they work well for me. Give them a shot :)
I have tried it and the uninstall speed is normal now, thanks a lot! :)

:up::up::up:

No problem at all. It was bugging me as well, a damn good plugin limited by its uninstall speed. At any rate i'm glad it helped.


Hamster, your changes were amazing for speed. I had a couple of problems with the original PRODUCT_UNINST_ROOT and PRODUCT_UNINST_KEY being replaced with INST_DIR_REG_ROOT and INSTDIR_REG_KEY, so I reverted that. I also updated the script so that it pays attention to the name defined inside the UNINSTALL_LOG var. I also noticed that it had problems removing folder outside of the base install directory (Such as those added to My Documents $DOCUMENTS), so I improved the uninstall loop to track any directories encountered. Since the default $INSTDIR sometimes is not recorded in the log, you may need to do a manual

push $INSTDIR
Call un.RemoveEmptyDirs
in your uninstall section

Originally posted by HaMsTeYr
Here it is, to use it:
Add
!include AdvUninstLog2.nsh

and since its a very makeshift modification, you can only use these macros

!insertmacro UNATTENDED_UNINSTALL

Section ""
!insertmacro UNINSTALL.LOG_OPEN_INSTALL
File "SomeFile"
!insertmacro UNINSTALL.LOG_CLOSE_INSTALL
SectionEnd

Function .onInit
!insertmacro UNINSTALL.LOG_PREPARE_INSTALL
FunctionEnd

Function .onInstSuccess
!insertmacro UNINSTALL.LOG_UPDATE_INSTALL
FunctionEnd

Section "Uninstall"
!insertmacro UNINSTALL.NEW_UNINSTALL "$OUTDIR"
SectionEnd

For the uninstall section, i don't think the OUTDIR should matter much as i've coded it such that it looks for the whole directory from the root drive.

Anyway, those are the ones i'm using at the moment and they work well for me. Give them a shot :)
I've noticed that most elements of the interactivity have been removed from your script... as well as any verification for the files having been changed.

Any plans to implement more in regards to those aspects? (Final install directory will not be removed if unlisted files are present. :( )

I removed a lot of elements, to keep it simple and fast. I hated the fact that it would take forever just for the installer to search for existing files back and forth, so I chopped it down to a few simple commands.

TBH though, I made those changed for my purposes, but they're not too difficult to modify. You could try making these modifications yourself, and see how you go, or if you detail it just a little bit more, maybe I'll help :P maybe. xD