![]() |
#1 |
Junior Member
Join Date: Aug 2008
Posts: 3
|
Rollback
Hello everybody, it's my first post.
I'm doing evaluation on nsis and inno to choose the one that suits me more. I've read and seen enough, just need one last question answered. Does NSIS supports rollback functionality? I mean, if I have a scenario of upgrade, which contains copying a lot of files over existing installation and after that calling some sophisticated sql scripts, which can fail, will it be possible to (depending on sql actions outcome) rollback the whole installation to the point before upgrade? I am pretty sure Inno has it. p.s. I don't want no flamewar, just a simple answer, perhaps with some links. |
![]() |
![]() |
![]() |
#2 |
Junior Member
Join Date: Aug 2008
Posts: 3
|
oh come on!
Nobody? |
![]() |
![]() |
![]() |
#3 |
Moderator
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 5,508
|
no, there is no rollback, you could copy the original files to a backupdir and "restore" from that if needed
IntOp $PostCount $PostCount + 1 |
![]() |
![]() |
![]() |
#4 |
Junior Member
Join Date: Aug 2008
Posts: 3
|
thx man.
I was already trying this route. In my case it also means copying a db. But it should be do-able... |
![]() |
![]() |
![]() |
#5 |
Moderator
Join Date: Nov 2002
Location: Surrey, England
Posts: 8,434
|
|
![]() |
![]() |
![]() |
#6 |
Junior Member
Join Date: Mar 2008
Posts: 33
|
rollback.nsh
I'm working on a nice rollback include. ( Aptly titled rollback.nsh ) Just a set of macros really, but it sets up a log that can be saved to a provided path.... builds the log...as you install or edit files and registry entries... and when you're done you close the "session". Then later you could come back and execute the rollback.
Works well for my application which can't really depend on having a clean folder for its files. So 'rollback' means recopying whatever files I detect that I've stepped on, back into the working folder on a rollback. ( Essentially parsing the log file... for FILE entries, and putting it back where the PATH attribute says to go. ) Maybe we should include a log for SQL calls to? Or better a log to execute SQL files against a database... that might abstract your issue better. It'd be ready for a demo as a general include, except that I'd like to include the ability to tie in a CallBack on a failed copy.... i.e. If you tried to restore a file it was tied up or something. Currently I have a string that gets read from the log file and passed to ExecWait but that's just a bit limiting and somewhat impractical. I'd rather be able to read a string from the log file and call back a function in the NSIS script... like so: Function handleErrorWithCustomCallback MessageBox MB_OK "Handled Error." FunctionEnd ## SNIP ## ## In some Section or function... ReadFile $myFile $myCallBackString ; blah blah blah ## myCallBackString now has "handleErrorWithCustomCallback" Call $myCallBackString ; but this isn't resolving.... ; macros seem to do something like this with ${_label} but not quite.... The lack of runtime binding/resolution seems to not resolve this.... or maybe I'm not resolving the var's contents like I should be.... any comments Stu? |
![]() |
![]() |
![]() |
#7 |
Moderator
Join Date: Nov 2002
Location: Surrey, England
Posts: 8,434
|
Try using GetFunctionAddress.
Stu |
![]() |
![]() |
![]() |
#8 |
Junior Member
Join Date: Mar 2008
Posts: 33
|
Not the answer.... still requries compile time binding.
Sadly, that doesn't seem to work.... for example....
Function testCallback MessageBox MB_OK "Called it" FunctionEnd ;-------------------------------- ; There are no sections or pages in this installer. It just executes the .onInit and closes. ; Function .onInit var /GLOBAL testTheCallback StrCmp "1" "0" 0 +2 call testCallback ; this so it doesn't zero the code. MessageBox MB_OK "Testing callback:" StrCpy $testTheCallback "testCallback" GetFunctionAddress $R1 $testTheCallback ;Doesnt' work. ### ## WORKS: GetFunctionAddress $R1 "testCallback" ## BUT SINCE ITS READING IT FROM A FILE ITS NOT USEFUL. ####################################################### Call $R1 FunctionEnd GetFunctionAddress seems to want the literal function name entered, not some variable..... |
![]() |
![]() |
![]() |
#9 |
NSIS MUI Dev
Join Date: Nov 2001
Posts: 3,717
|
The actual names of function and variables are not included in the compiled installer.
|
![]() |
![]() |
![]() |
#10 |
Junior Member
Join Date: Mar 2008
Posts: 33
|
agreed......
Considering that we're sort of operating in an Assembly like stack mentality... I understand that the nice readable names get stored merely as a memory location.
Are you saying that there is no runtime-linking to functions based on an evaluated string? i.e...... something like this in a javascript mentality might look like.... ( during runtime... obviously ) myVar = eval("customFunctionName"); Thus, we could use a line like to this to interpret text files into operating instructions at runtime... such as a call back function for some condition. What you are saying is that there is no way to reference that function abstractly in code during runtime? |
![]() |
![]() |
![]() |
#11 |
Member
Join Date: Jul 2003
Posts: 83
|
Sorry to bump an old thread, but I did have something to contribute.
We are using quite an old version of NSIS, (2.14), with some custom modifications to the NSIS code to provide a primitive (but works for us) automated rollback system. Deep down in the NSIS core, where the file is actually written to disk, before the write is actually done, we check to see if it already exists, if it does, we append the existing filename with the .previous extension and then write the new file. On uninstall, it's simply a process of recursively scanning the installation folder, if we find a .previous, delete the original file and restore the .previous version. The whole .previous creation process can be enabled or disabled during the script execution by setting $R9 (this clearly could be improved to make it a keyword) Anyone want the patch? (the reason we are still using NSIS 2.14 is because of the source changes we made, we don't see any issues with this old NSIS version, and don't want to constantly merge our NSIS, so there is a benefit for us if we can get this patch, or equivalent functionality into NSIS, so we can use standard NSIS) |
![]() |
![]() |
![]() |
#12 |
Major Dude
Join Date: Oct 2006
Posts: 1,892
|
There is no need to edit the NSIS sourcecode to get this behaviour. It's extremely simple to do this in script alone. I therefore very much doubt that your patch will be merged into the trunk.
|
![]() |
![]() |
![]() |
#13 | |
Major Dude
Join Date: Jun 2001
Posts: 1,173
|
Quote:
Not that I'm advocating this patch per se - but unless I missed something, you're going to need quite a bit of code to actually get this sort of behavior out of NSIS. There's probably examples in the wiki that make it easier because you don't have to come up with something from scratch*, but... For single files, you'd have to define a macro that replaces the File command you'd normally use which... 1. Checks if the file exists 2. If it does, creates a backup* 3. Tries to overwrite the file 3a. If it succeeds - great, done 3b.1 If not, delete the backup 3b.2 Catch the error with custom handling if desired (see some other thread on this) * and in the backup section check if you can actually back up to the location you want to back up to. And that's single files. As soon as you use the File command to include multiple files or files recursively, you have to either... A. Drop that construction entirely and make a pre-installer build installer that generates a file inclusion list for the actual installer, or B. First extract the files to a temporary location and instead of using the File command to place the files directly, find the files that were created in the temporary location and use CopyFiles and CreateDirectory instead (further handling is similar to the above). You'd need these as separate macros as well - or as a single macro but for 'single file' calls you'd have to explicitly indicate that it is such. e.g. !macro macroname source dest recursive For a single file would always have to specify the 'recursive' bit as being 'false', '0', or whatever one chooses. This applies for every parameter in the File command that you'd want to support. Adding support for /x (exclude files) means adding another parameter... now a single file call might end up looking like: ${macroname} "somefile.ext" "$InstDir\somefile.ext" 0 0 Alternatively you'd have to define them before your call.. or callS in which case you have to make sure you don't forget to undefine them afterward.. etc. It's not impossible, but 'extremely simple' is not how I would choose to describe it in general ![]() |
|
![]() |
![]() |
![]() |
#14 | |
Major Dude
Join Date: Oct 2006
Posts: 1,892
|
Quote:
(You could of course make two macros, one single and one recursive/wildcard...) |
|
![]() |
![]() |
![]() |
#15 | ||
Major Dude
Join Date: Jun 2001
Posts: 1,173
|
Quote:
So now you need macros: File FileR FileX FileRX Now add /a and /nonfatal ![]() ${NonFatal} true ${FileSomething} a x ... ${FileSomething} b x ... ${FileSomething} c x ... ${NonFatal} False But you phrased it well when you said Quote:
![]() |
||
![]() |
![]() |
![]() |
#16 |
Member
Join Date: Jul 2003
Posts: 83
|
And this was precisely the reason we decided on a change deep down at file writing level, as it works regardless of how the file is added to the installer :-)
|
![]() |
![]() |
![]() |
#17 | |||
Major Dude
Join Date: Jun 2001
Posts: 1,173
|
Quote:
Quote:
Quote:
Doing it 'right' will never be easy - if even possible at all - but there's certainly room for improvement. |
|||
![]() |
![]() |
![]() |
#18 | ||
Junior Member
Join Date: Apr 2011
Posts: 1
|
Quote:
Quote:
|
||
![]() |
![]() |
![]() |
|
Thread Tools | Search this Thread |
Display Modes | |
|
|