sazr
sazr

Reputation: 25938

NSIS Replace Line in File: Never reads file & never identifies the correct line

I am attempting to replace a line in a file.

My Problem: I can never find the line I am looking for in a file. My function finds the line I want to replace but doesn't correctly identify it as the one I want to replace or maybe it fails to open the file(the path to the file is correct).

If you test the my function with the following simple textfile it still fails:

abc
test
data

Can you help me to get my function to correctly replace a line in a file?

# usage that fails to work
Push "C:\Users\blah\Desktop"
Push "test.txt"
Push "abc"
Push "def"
Call ReplaceLineInFile

Function ReplaceLineInFile
    # T-3 = nDir
    # T-2 = nFile
    # T-1 = targetLine
    # TOP = replaceLine  # TOP is top of stack
    # $4  = tempName
    # $5  = numTargetLinesFound

    Pop $3  # replaceLine
    Pop $2  # targetLine
    Pop $1  # nFile
    Pop $0  # nDir
    StrCpy $1 "$0\$1" # create the string 'C:\users\blah\mytext.txt'
    IntOp $5 0 + 0
    MessageBox MB_OK "ReplaceLineInFile: dir: $0$\r$\nfile: $1$\r$\ntarget: $2$\r$\nreplace: $3" 

    ClearErrors
    FileOpen $8 $1 "r"                         ; open target file for reading
    GetTempFileName $4                         ; get new temp file name
    FileOpen $7 $4 "w"                         ; open temp file for writing
    loop:
       FileRead $8 $6                          ; read line from target file
       IfErrors done                           ; check if end of file reached
       MessageBox MB_OK "Line: $6$\r$\nTarg: $2"
       StrCmp $6 "$2$\r$\n" 0 +3               ; compare line with search string with CR/LF
          StrCpy $6 "$3$\r$\n"                 ; change line
          IntOp $5 $5 + 1
       StrCmp $6 "$2" 0 +3                     ; compare line with search string without CR/LF (at the end of the file)
          StrCpy $6 "$3"                       ; change line
          IntOp $5 $5 + 1
       FileWrite $7 $6                         ; write changed or unchanged line to temp file
       Goto loop

    done:
       FileClose $8                            ; close target file
       FileClose $7                            ; close temp file
       Delete $1                               ; delete target file
       CopyFiles /SILENT $4 $1                 ; copy temp file to target file
       Delete $4                               ; delete temp file
       MessageBox MB_OK "Targets found: $5"

FunctionEnd

Upvotes: 2

Views: 2011

Answers (1)

RobeN
RobeN

Reputation: 5456

You should check LineFind macro for NSIS: http://nsis.sourceforge.net/LineFind

To replace lines in files you can try to use:

Name "Text Replacer"
OutFile "TextReplacer.exe"

;[DEFINES] You define String To Find and String To Replace

!include "TextFunc.nsh" 
!insertmacro LineFind 
!include "Sections.nsh" 

!define STRTOFIND  "BaseLine1: TextThatShouldBeChanged"
!define STRTOREPL  "BaseLine1: TextHasBeenCHANGED!!!"
!define STRTOFIND2  "[BaseLine2=TextThatShouldBeChanged;"
!define STRTOREPL2  "[BaseLine2=TextCHANGED!!!;"

;[Functions] You create Line Replace Functions for each line

Function LineFindCallback
    StrLen $0 "${STRTOFIND}"
    StrCpy $1 "$R9" $0
    StrCmp $1 "${STRTOFIND}" 0 End
    StrCpy $R9 "${STRTOREPL}$\r$\n"
    End:
    Push $0
FunctionEnd
Function LineFindCallback2
    StrLen $0 "${STRTOFIND2}"
    StrCpy $1 "$R9" $0
    StrCmp $1 "${STRTOFIND2}" 0 End
    StrCpy $R9 "${STRTOREPL2}$\r$\n"
    End:
    Push $0
FunctionEnd

;[Sections] You call function for specific line in specific file
;Input and Output file can be same or different
;If Output file name is different (new file is created)
;then every next LineFind call should take Previous Output file as Input file

Section "Replace 1" Section1
SectionIn 1 +2
${LineFind} "$EXEDIR\FILE.ini" "$EXEDIR\FILE.ini" "1:-1" "LineFindCallback"
    IfErrors 0 +2
    MessageBox MB_OK "Error"
${LineFind} "$EXEDIR\FILE.ini" "$EXEDIR\FILE.ini" "1:-1" "LineFindCallback2"
    IfErrors 0 +2
    MessageBox MB_OK "Error"
SectionEnd

Create FILE.ini containing and keep it in same folder which you will have TextReplacer.exe:

This is File.ini file
That line will not be changed
BaseLine1: TextThatShouldBeChanged
This line=is just a dummy line
[BaseLine2=TextThatShouldBeChanged;
File.ini end

Upvotes: 3

Related Questions