How to split string in NSIS - nsis

String "jdbc:postgresql://localhost:5432/DatabaseName"
My requirement is to get only the DatabaseName from the above string.
I tried below link but it is not worked.
${Explode} $0 "jdbc:postgresql://localhost:5432/" "$v1"
It give the error invalid command.
http://nsis.sourceforge.net/Explode
How it is possible in NSIS language. As i'm not more familiar with NSIS language.
Please do the needful help. Thanks in advance.

If all you need is to get the rest of the string after the last / you can just use some basic NSIS string handling:
Section
StrCpy $0 "jdbc:postgresql://localhost:5432/DatabaseName"
StrCpy $1 0
loop:
IntOp $1 $1 - 1 ; Character offset, from end of string
StrCpy $2 $0 1 $1 ; Read 1 character into $2, -$1 offset from end
StrCmp $2 '/' found
StrCmp $2 '' stop loop ; No more characters or try again
found:
IntOp $1 $1 + 1 ; Don't include / in extracted string
stop:
StrCpy $2 $0 "" $1 ; We know the length, extract final string part
DetailPrint "|$2|"
SectionEnd

You should try the NSISpcre plugin, maybe you need some nasty regex :p

The WordFind function lets you do that, take a look at its examples

Related

How to prefix log entries generated from NSIS exe with current date and time without overwriting registers?

I want to write timestamps at the start of each line entered into a log during the run of an NSIS (Nullsoft) .exe program.
It appears the only valid pattern to call the GetTime function is:
${GetTime} "" "L" $0 $1 $2 $3 $4 $5 $6
This results in overwriting the registers ($0, $1, etc.) in the calling .nsh files. Is there a way to prevent this?
For example:
The global_defines.nsh contains something like this:
!macro WriteLog text
...
FileWrite $mylogfile '${text}'
${GetTime} "" "L" $0 $1 $2 $3 $4 $5 $6
FileWrite $mylogfile "$2-$1-$0 $4:$5:$6 '${text}'"
...
and the calling .nsh file contains something like this:
StrCpy $1 'run_this_script'
!insertmacro WriteLog "About to run: $1"
ExecDos::exec /TOWINDOW $1
pop $0
!insertmacro WriteLog "script run returned $0"
This results in $1 getting set to the month value set in the macro.
A separate posting:
https://stackoverflow.com/a/19622151/6388369
shows using $year, etc., but this does not compile.
$year is a custom variable:
Var year
Section
${GetTime} ... $year ...
FileWrite ...
SectionEnd
The other alternative is to save/restore the old data if you need to preserve it (which you usually need to do in helper macros):
Section
Push $0
Push $1
Push ...
${GetTime} ... $0 $1 ...
FileWrite ...
Pop ...
Pop $1
Pop $0
SectionEnd

NSIS Inetc get: can I make the downloaded file a variable?

The code is working when I have File_1234.exe added there. But the file name changes and download.php redirects to the exe. So instead of having a fixed file name there, I would like to have a code where i don't need to specify file name.
Is it possible to replace the first File_1234.exe with code to download whatever file the URL gives, and therefore to replace the second File_1234.exe with code that would run (ExecShell) this downloaded file?? Thanks
The code itself is here:
Section "File"
inetc::get "http://example.com/download.php" "$pluginsdir\File_1234.exe"
Pop $0
DetailPrint "Result: $R0"
ExecShell "" '"$pluginsdir\File_1234.exe"'
SectionEnd
INetC does not have a flag that passes the INTERNET_FLAG_NO_AUTO_REDIRECT flag to WinInet so there is no way to do a head request and find the location when the server returns a 30x redirection code.
If you can modify download.php to just return the final URL as a small text file when a special parameter is present then you can make two GET requests, the first to get the name and the second to do the main download:
Section
InitPluginsDir
StrCpy $0 "http://example.com/download.php?fileid=1234"
inetc::get /SILENT "$0&locationonly=1" "$PluginsDir\location.txt" /END
FileOpen $1 "$PluginsDir\location.txt" R
FileRead $1 $2
FileClose $1
StrLen $1 $2
loop:
IntOp $1 $1 - 1
StrCpy $3 $2 1 $1
StrCmp $3 '/' 0 +4
IntOp $1 $1 + 1
StrCpy $3 $2 "" $1
Goto +2
StrCmp $3 "" 0 loop
StrCmp $3 "" nofilename
inetc::get "$0" "$PluginsDir\$3" /END
Goto done
nofilename:
MessageBox mb_iconstop "Unable to parse filename from $2"
done:
SectionEnd
This example assumes that http://example.com/download.php?fileid=1234 would download the file but http://example.com/download.php?fileid=1234&&locationonly=1 would only return a URL like http://example.com/myfiles/whatever.exe
This is a 5 year later answer to help who ever might want to know how to get inetc::get output into a variable ;)
Obviously you found a solution since then... anyway:
inetc::get has a nice option /TOSTACK that does this.
Here's how on your example:
!include LogicLib.nsh
Section "File"
inetc::get /TOSTACK "http://example.com/download.php" ""
Pop $0
DetailPrint "Result: $0"
${If} $0 == 'OK'
Pop $0
StrCpy $filename $0
inetc::get /TOSTACK "http://example.com/$filename" "$PluginsDir\$filename"
Pop $0
${If} $0 == 'OK'
ExecShell "" '"$pluginsdir\$filename"'
${Else}
MessageBox MB_OK "Cannot download file $filename"
${EndIf}
${Else}
MessageBox MB_OK "Cannot fetch filename to download"
${EndIf}
SectionEnd
This is possible if your "http://example.com/download.php" returns URL of file to download.
What I mean: download.php returns URL as text ("http://example.com/file_12345.exe").
1) This text is downloaded with inetc to some local file and read into variable.
2) Use Inetc to download the file from URL (specified in variable) again as a resulting .exe file.
Is this acceptable for you?

How can I search for a string in a txt file?

Is there some way that I can search in a example.txt file for a string example?
I tried Fileread and Fileseek but it is not working yet... later I'd like to write to the file, that's why I use FileOpen with the a append attribute:
FileOpen $4 "$SYSDIR\drivers\etc\hosts" a
FileSeek $4 0 SET
FileRead $4 $1
${If} $1 != "example"
Strcmp $1 "example" end 0
Or can I walk through the file with While? But when does the file end?
Update
!define IP_AND_DISPATCHER "30.0.0.0 dispatcher"
FileOpen $0 "$SYSDIR\drivers\etc\hosts" a
loop:
FileRead $0 $2
IfErrors done
Messagebox MB_OK "$2"
StrCmp $2 "${IP_AND_DISPATCHER}$\r$\n" 0 loop
MessageBox MB_OK "$${IP_AND_DISPATCHER} found"
FileClose $2 ;close file
Quit
done:
FileSeek $0 0 END
FileWrite $0 "$\r$\n" ; new line
FileWrite $0 "${IP_AND_DISPATCHER}" ;write ip and dispatcher
FileWrite $0 "$\r$\n" ; extra line
FileClose $0 ;close file
Now its working, but is there a way to not write the 30.0.0.0 dispatcher so not the entire line... just, for example, the dispatcher word?
The NSIS wiki contains several examples for text files manipulations, with
2 examples for searching in a file with or without comments defining function for delegating the tedious string manipulations based on StrCmp
and another example for writing in a file, while there is another for replacing text
You can base your own work on these examples.

How to compare two files in NSIS?

I have created exe using nsis.I have used following code for comparing two files.
Function compare
IfFileExists "$INSTDIR\old.properties" 0 filenotfound
FileOpen $0 "$INSTDIR\old.properties" "r"
FileOpen $1 "$INSTDIR\new.properties" "w"
loop:
FileRead $0 $2
MessageBox MB_OK "old $2"
FileRead $1 $3
MessageBox MB_OK "new $3"
IfErrors done
strcmp $3 $2 loop here
here:
FileWrite $1 $2
Goto loop
done:
FileClose $0
FileClose $1
filenotfound:
MessageBox MB_OK "File not found"
FunctionEnd
Read first text of the old property compare first text of the new property if matches go to next word of the both files.else old property values should be replaced in new property file.but if the string mismatches replacing string in the new property file doesnot happen.
How to solve this? what am i did wrong?
FileOpen $1 "$INSTDIR\new.properties" "w" will erase everything in new.properties, use "a" if you want to keep its content.
I don't really fully understand what you are trying to do since "compare files" usually means a read-only operation, you are also writing but you don't seem to actually replace a specific old line with a new different one...

NSIS Find all .txt files

I currently have a check to find all text files in $INSTDIR, shown below.
However, there could potentially be subdirectories, such as $INSTDIR\mySub, which contains additional .txt files. Is there a way to keep a similar loop structure but search all subdirectories as well?
FindFirst $R0 $R1 "$INSTDIR\*.txt"
IfErrors ExitInstaller 0
LoopIt:
Messagebox MB_OK "Do some processing on $R1"
FindNext $R0 $R1
IfErrors 0 LoopIt
Function ProcessTextFiles
Exch $0
Push $1
Push $2
FindFirst $1 $2 "$0\*.txt"
loop:
IfErrors end
DetailPrint 'Found "$0\$2"'
FindNext $1 $2
goto loop
end:
FindClose $1
FindFirst $1 $2 "$0\*.*"
dirloop:
IfErrors dirend
IfFileExists "$0\$2\*.*" 0 dirnext
StrCmp $2 "." dirnext
StrCmp $2 ".." dirnext
Push "$0\$2"
call ${__FUNCTION__}
dirnext:
FindNext $1 $2
goto dirloop
dirend:
FindClose $1
Pop $2
Pop $1
Pop $0
FunctionEnd
section
push "$InstDir"
call ProcessTextFiles
sectionend
Try to use the Locate function instead -- it could be much better solution. You can write options to find with (or without) subdirectories, define mask and so on. See http://nsis.sourceforge.net/Locate for doc and examples.

Resources