Archive: String Replacing and Error Handling


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. ;)


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.


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.


Did you search at wiki? Most likely there's a function tailored for you ;)


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