carlosfocker
3rd August 2007 16:17 UTC
String Replacing and Error Handling
I have to question/comments. Is there a function/macro included in the NSIS headers that can do exactly what ReplaceLineSt does. I know you can use linefind and call a function if the file is found but this creates a function for each file I have to edit. I would like to just tell the macro/function what file I need to edit, what string to look for and what to replace it with.
The second thing is the error handling in NSIS. From what I can see is that the only error handling that is used is the set errors and clear them. What if something goes wrong in my installer and I want the user to a have a proper error written to the log. It would be nice to handle all exception in the functions I am calling to. If I am completely out of line just put me in my place. ;)
Red Wine
3rd August 2007 17:34 UTC
Feel free to build your own macro that suits your needs, after all the meaning of the macro is to avoid repeating code.
Almost every nsis command sets the error flag, for instance ReadRegStr sets the error flag if the string isn't present.
Using the IfErrors instruction you're able to handle every error and write a detailed log if you like.
carlosfocker
3rd August 2007 17:34 UTC
Well it seems ReplaceLineSt doesnt work the way I want it to. What I want is to replace a single string inside a text file.
Red Wine
3rd August 2007 17:40 UTC
Did you search at wiki? Most likely there's a function tailored for you ;)
carlosfocker
3rd August 2007 18:15 UTC
I ended up going with AdvReplaceInFile.
By biggest concern with custom error handling for each call is you have to write a lot of duplicate code.
Call Command that sets errors
${If} ${Errors}
DetailPrint 'Error: Custom error message'
${EndIf}
It would be nice if when an error occurs in a function that you could throw a string to an error handler that prints it out. I will look into what might be possible later.
I tailored AdvReplaceInFile to include error handling. So now instead of just quiting out of the function when certain errors occur, it gives a message describing what happened.
Function AdvReplaceInFile
Exch $0 ;file to replace in
Exch
Exch $1 ;number to replace after
Exch
Exch 2
Exch $2 ;replace and onwards
Exch 2
Exch 3
Exch $3 ;replace with
Exch 3
Exch 4
Exch $4 ;to replace
Exch 4
Push $5 ;minus count
Push $6 ;universal
Push $7 ;end string
Push $8 ;left string
Push $9 ;right string
Push $R0 ;file1
Push $R1 ;file2
Push $R2 ;read
Push $R3 ;universal
Push $R4 ;count (onwards)
Push $R5 ;count (after)
Push $R6 ;temp file name
GetTempFileName $R6
IfFileExists $0 0 FileOpenError
FileOpen $R1 $0 r ;file to search in
FileOpen $R0 $R6 w ;temp file
IfFileExists $R6 0 TempFileOpenError
StrLen $R3 $4
StrCpy $R4 -1
StrCpy $R5 -1
goto loop_read
FileOpenError:
detailprint 'Error: $0 does not exist'
Goto ErrorExit
TempFileOpenError:
detailprint 'Error: Temp file could not be created to edit $0'
Goto ErrorExit
FileWriteError:
detailprint 'Error: Could not write to $0'
Goto ErrorExit
loop_read:
ClearErrors
FileRead $R1 $R2 ;read line
IfErrors exit
StrCpy $5 0
StrCpy $7 $R2
loop_filter:
IntOp $5 $5 - 1
StrCpy $6 $7 $R3 $5 ;search
StrCmp $6 "" file_write2
StrCmp $6 $4 0 loop_filter
StrCpy $8 $7 $5 ;left part
IntOp $6 $5 + $R3
IntCmp $6 0 is0 not0
is0:
StrCpy $9 ""
Goto done
not0:
StrCpy $9 $7 "" $6 ;right part
done:
StrCpy $7 $8$3$9 ;re-join
IntOp $R4 $R4 + 1
StrCmp $2 all file_write1
StrCmp $R4 $2 0 file_write2
IntOp $R4 $R4 - 1
IntOp $R5 $R5 + 1
StrCmp $1 all file_write1
StrCmp $R5 $1 0 file_write1
IntOp $R5 $R5 - 1
Goto file_write2
file_write1:
FileWrite $R0 $7 ;write modified line
IfErrors FileWriteError
Goto loop_read
file_write2:
FileWrite $R0 $R2 ;write unmodified line
IfErrors FileWriteError
Goto loop_read
exit:
FileClose $R0
FileClose $R1
SetDetailsPrint none
Delete $0
Rename $R6 $0
Delete $R6
SetDetailsPrint both
ErrorExit:
Pop $R6
Pop $R5
Pop $R4
Pop $R3
Pop $R2
Pop $R1
Pop $R0
Pop $9
Pop $8
Pop $7
Pop $6
Pop $5
Pop $0
Pop $1
Pop $2
Pop $3
Pop $4
FunctionEnd