Setting different Start Menu icon in NSIS script? - nsis

Is it possible to use a different icon for the Start Menu shortcut versus the Desktop shortcut in NSIS?
On the desktop, the shortcut is perfect size, at 48x48. However in the start menu, the icon gets sized down to what I'm assuming is 32x32 and looks choppy.
CreateShortCut "$SMPROGRAMS\${NAME}.lnk" \
"$INSTDIR\$(shortcut_name).lnk"
CreateShortCut "$DESKTOP\${NAME}.lnk" \
"$INSTDIR\$(shortcut_name).lnk"
Thanks very much.

A Windows icon can contain multiple images with different sizes, your icon should ideally contain 16x16, 24x24, 32x32, 48x48, 128x128 and 256x256 pixel images.
The size of icons on the desktop and start-menu depends on system settings and DPI.
For most installers you would just use CreateShortCut "$SMPROGRAMS\${NAME}.lnk" "$INSTDIR\myapp.exe" and myapp.exe would have the icon in its resources. You can also use a external .ico file: CreateShortCut "$SMPROGRAMS\${NAME}.lnk" "$INSTDIR\myapp.exe" "" "$INSTDIR\myapp.ico" 0

If you look at the specification for CreateShortcut you'll see that the arguments are as follows.
[/NoWorkingDir] link.lnk target.file [parameters [icon.file [icon_index_number [start_options [keyboard_shortcut [description]]]]]]
Since you don't have any parameters I believe you will have to pass an empty string to that. So something like this will probably do it.
CreateShortCut "$SMPROGRAMS\${NAME}.lnk" \
"$INSTDIR\MyApplication.exe" \
"" \
"$INSTDIR\MyApplication.exe"`
Or if you have another icon in your main executable and want to use that you can specify an index after the icon path like this.
CreateShortCut "$SMPROGRAMS\${NAME}.lnk" \
"$INSTDIR\MyApplication.exe" \
""\
"$INSTDIR\MyApplication.exe" 2`

Related

Write russian symbols in ini file with NSIS installer

I have several UTF8-BOM ini-files and using Unicode nsis installer.
Using WriteINIStr is working great with latin symbols, but russian symbols are not displayed.
For example this code is not working:
WriteINIStr $File "TestSection" "Test" "Тест"
I have a few thoughts about encoding file into UTF16 and backwards, but I don't think that's the right path.
If the .ini has a UTF-16LE BOM the Windows ini functions will write to the file with UTF-16 encoding.
FileOpen $0 $INSTDIR\file.ini a
FileWriteUTF16LE /BOM $0 ""
FileClose $0
WriteIniStr $INSTDIR\file.ini foo bar "${U+2115}SIS"
As long as other programs that access this file also uses the standard Windows ini functions this will work. If the other programs uses custom parser functions that require UTF-8 then this will not work and you have to convert the file encoding.

How to delete the startup file itself test.exe?

After running the .exe file, I need to delete the file so that it no longer exists.
I have a script that I create a file to run, but how to delete it after launch?
Outfile test.exe
Requestexecutionlevel user
Setcompressor LZMA
Page instfiles
Section
;Not a good idea to hardcode the destination like this,
;normally you would use a directory page so the user can choose
SetOutPath "c:\SaveToThisFolder"
;Take thefile.txt from the system you compile on and output it on the end users system
;into the directory specified by the SetOutPath call
File "thefile.txt"
Sectionend
How to delete file test.exe after run?
It is hard for a Windows process to delete itself and NSIS does not really support it but you can try the SelfDel plug-in

Space required on MUI_PAGE_DIRECTORY is 0.0KB

I'm writing an installer for Windows application. I'm using MUI for NSIS. One of the pages of the installer is Directory Page, where I have the "Space required" field. The problem is that the space required is always 0.0KB.
I was looking for some answers, but all I found was that space is calculated automatically. I wonder if there is some way to check which folder size this macro gets? Or any other ideas?
;Pages
; Installation
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_LICENSE "#CPACK_RESOURCE_FILE_LICENSE#"
!insertmacro MUI_PAGE_DIRECTORY
Page custom pgAppLanguageCreate
The size is automatically calculated by the File instructions in Sections plus any extra you add with AddSize.
If you are not happy with this calculation you can force a specific size in .onInit with SectionSetSize.
I found what causes the problem.
In the "Installer Section" I used a function that copies all files.
Instead of calling it here, I just paste the entire function and now that works. It looks like you cant use "File" instruction in function because it doesn't add size to the required space this way.
If you use it in section, it works perfectly.
; Installer Sections
Section "install" Install
${If} $instState != "1"
Call deleteAllFiles
Call deleteInfoFromRegistry
Call deleteShortcut
${EndIf}
SetOutPath "$INSTDIR"
; copy files
File ${ICON}
File "slicer_license"
File /r "${INSTALL_FILE}\package\"
;File "README.txt" ;Readme file.
Call createShortcut
Call addInfoToRegistry
Call setAppLanguageShortcut
Call createLanguageFile
SectionEnd

How do I execute the app right after installation ... with arguments?

My installation EXE should unzip itself in a temp folder, then execute an app therein (with passing args), return and delete the temp folder again.
How do I write the nsi script?
It sounds to me like you are trying to create a portable application. Portable applications are always better when the original author adds support for it because it can handle registry and other configuration files correctly.
If you still want to create a launcher application you can do something like this:
OutFile "MyLauncher.exe"
RequestExecutionLevel User
SilentInstall Silent
SetCompressor LZMA
!include FileFunc.nsh
!insertmacro GetParameters
Section
${GetParameters} $1
InitPluginsDir
SetOutPath $PluginsDir
File "c:\myfiles\MyApp.exe"
File /r "c:\myfiles\otherfiles\*.*" ; If you need to include other files required by the application
ExecWait '"$PluginsDir\MyApp.exe" /param1 "pa ra m2" /param3 $1' $0 ; $1 contains the parameters passed to your launcher, remove it if you don't want to pass those arguments
SetErrorLevel $0
SetOutPath $Temp ; Don't lock $PluginsDir so it can be deleted automatically by the installer
SectionEnd
Answering my own question.
The required nsi script skeleton should look like this:
# The name of the installer (arbitrary)
Name "hello"
# The name of the installation file
OutFile "hello.exe"
# where put the installation - other options would be $TEMP, etc.
InstallDir $DESKTOP
RequestExecutionLevel user # no Windows UAC popup please!
SilentInstall silent # completely silent install
SetCompressor /SOLID /FINAL lzma # max compression for inst. file
# The stuff to install
Section ""
SetOutPath $INSTDIR # where to install (overwritable by user!)
File /r D:\...\... # where the install material lives
SectionEnd
# this function auto-runs after installation is fine
Function .onInstSuccess
# parameter are passed through via $CMDLINE
ExecWait '"$OUTDIR\hello.dist\hello.exe" $CMDLINE'
RMDir /r "$OUTDIR\hello.dist" # remove install folder again
FunctionEnd

Install from dynamic location

I have 2 versions of the same exe file for my project. The installer is supposed to pick one of the 2 versions depending on some conditions.
In a normal case i would do File executable\myExe.exe. Because i now have 2 versions of the file, i would have to do something like File "${ExeSourcePath}\myExe.exe", and $ExeSourcePath is determined by checking various conditions. When compiling this code i get
File: "${ExeSourcePath}\myExe.exe" -> no files found.
Anyone knows why? I'm only allowed to use fixed paths with the File command or am i doing something wrong?
${ExeSourcePath} is a precompiler define and $ExeSourcePath is a variable used at runtime, the File command can only use precompiler defines.
There are two ways you can handle this:
A) Include both files and decide at runtime based on the users system or choices made during install:
!include LogicLib.nsh
Section
ReadRegStr $0 HKLM "Software\foo\bar" baz
${If} $0 > 5
File "c:\myproject\version2\app.exe"
${Else}
File "c:\myproject\version1\app.exe"
${EndIf}
SectionEnd
B) Only include one file based on command line passed to makensis (/Dusev2 app.nsi) or something on your system:
Section
!define projectroot "c:\myproject"
!searchparse /noerrors /file ....... usev2 ;Or you can use !system etc
!ifdef usev2
File "${projectroot}\version2\app.exe"
!else
File "${projectroot}\version1\app.exe"
!endif
SectionEnd

Resources