Adding extra command to cpack - NSIS packager/installer - installation

I want to package a project of mine for windows with CPack and NSIS using an already existing
GeneratorConfig.cmake file where I want to add an extra command that will copy an .ini file called myProject.ini into %APPDATA%/myProject/myProject.ini .
This is GeneratorConfig.cmake
SET(INSTALL_AN_ALREADY_EXISTING_DIR ".")
##########################################################################
## Begin NSIS Specific options
##------------------------------------------------------------------------
if(CPACK_GENERATOR MATCHES NSIS)
# Additional NSIS commands to uninstall start menu shortcuts
SET(CPACK_NSIS_DELETE_ICONS_EXTRA
"Delete \"$SMPROGRAMS\\$MUI_TEMP\\${PROJECT_NAME}.lnk\"
StrCmp \"$INSTALL_DESKTOP\" \"1\" 0 +2
Delete \"$DESKTOP\\${PROJECT_NAME}.lnk\" ")
# The display name string that appears in the Windows Add/Remove Program control panel
SET(CPACK_NSIS_DISPLAY_NAME "${PROJECT_NAME} ${PROJECT_VER_MAJOR}.${PROJECT_VER_MINOR}")
SET(CPACK_NSIS_DISPLAY_NAME_SET "TRUE")
# Extra NSIS commands that will be added to the end of the install Section, after your
# install tree is available on the target system.
SET(CPACK_NSIS_EXTRA_INSTALL_COMMANDS
"CreateShortCut \"$SMPROGRAMS\\$STARTMENU_FOLDER\\${PROJECT_NAME}.lnk\" \"$INSTDIR\\.\\bin\\${PROJECT_EXE} \" -previousworkingdir \"$INSTDIR\\.\\bin\\app_icon.ico\"
StrCmp \"$INSTALL_DESKTOP\" \"1\" 0 +2
CreateShortCut \"$DESKTOP\\${PROJECT_NAME}.lnk\" \"$INSTDIR\\.\\bin\\${PROJECT_EXE} \" -previousworkingdir \"$INSTDIR\\.\\bin\\app_icon.ico\"
")
# Extra commands to fix permissions of bin/licenses folder
SET(CPACK_NSIS_EXTRA_INSTALL_COMMANDS
"${CPACK_NSIS_EXTRA_INSTALL_COMMANDS}
ExecWait 'icacls \\\"$INSTDIR\\\\bin\\\\licenses\\\" /grant:r Users:\\\(OI\\\)\\\(CI\\\)\\\(F\\\)'
")
# A path to the executable that contains the installer icon.
SET(CPACK_NSIS_INSTALLED_ICON_NAME "${PROJECT__DIR}\\bin\\${PROJECT_EXE}")
# The default installation directory presented to the end user by the NSIS installer
SET(CPACK_NSIS_INSTALL_ROOT "$PROGRAMFILES64")
# Title displayed at the top of the installer
SET(CPACK_NSIS_PACKAGE_NAME "${PROJECT_NAME} ${PROJECT_VER_MAJOR}.${PROJECT_VER_MINOR}")
SET(CPACK_NSIS_PAGE_COMPONENTS " ")
SET(CPACK_NSIS_MUI_FINISHPAGE_RUN ${PROJECT_EXE})
endif(CPACK_GENERATOR MATCHES NSIS)
##------------------------------------------------------------------------
## End NSIS Specific options
##########################################################################
I tried to do this with the code below but this builds the package but doesn't
copy myProject.ini anywhere.
SET(CPACK_NSIS_EXTRA_INSTALL_COMMANDS
"CreateDirectory \"$ENV{APPDATA}\\myProject\",
SetOutPath \"$ENV{APPDATA}\\myProject\",
File \"myProject.ini\"
")
Any help or suggestions will be appreciated.

From what i can tell you are using not enough '\' symbols.
To clarify: that string is evaluated twice, once by CMake and once by CPack, and each time substitutions such as \->\ and \" -> " occur. Please check generated nsis project for what the actual generated commands are and whether all '"' are correctly set.
To summarize: try using this:
SET(CPACK_NSIS_EXTRA_INSTALL_COMMANDS
"CreateDirectory \\\"$ENV{APPDATA}\\\\myProject\\\",
SetOutPath \\\"$ENV{APPDATA}\\\\myProject\\\",
File \\\"myProject.ini\\\"
")

Related

7z Command Line Extract code does not extract files into specified folder

I have written a command line extract code :
7z x C:\\Users\\Anuj\\Desktop\\th.7z -p123 -oC:\\Program Files\\OpenVPN *.* -r"
Here the given Output path is :
C:\\Program Files\\OpenVPN *.* -r"
However The zip file gets extracted to :
C:\Program\
I have identified the problem too, the problem is the code cannot take spaces in file folder.if the file output is changed to C:\\ProgramFiles\\OpenVpn
It works. BUt if the path is C:\\Program Files\\OpenVPN It doesnt
I was getting the ACCESS DENIED error for the code below:
declare #unzip varchar(500)
set #unzip='"C:\Program Files\7-Zip\7z.exe" e D:\Documents\test_compress.zip -oD:\Documents\test_compress'
exec master..xp_cmdshell #unzip
All I had to do was allow the MSSQL application the FULL ACCESS control. To do that first find the application name :
exec master..xp_cmdshell 'whoami' -- nt service\mssqlserver
Now go to D:\Documents - Right Click the Documents folder - Click "Properties - Go to "Security" tab -- If MSSQLSERVER is not listed then Click "Edit" and then click "Add" -- Add "NT SERVICE\MSSQLSERVER" and now check the option "Full Control" Allow
From: http://7zip.bugaco.com/7zip/MANUAL/syntax.htm
Wildcards or filenames with spaces must be quoted:
"Dir\Program files\*"
Dir\"Program files"\*
Hope this helps.

NSIS - EnvVarUpdate overwrites system path when path is too long, is there a workaround?

Here is my simple code:
!include "EnvVarUpdate.nsh"
Outfile "text.exe"
Section
${EnvVarUpdate} $0 "PATH" "A" "HKLM" "C:\Program Files\something"
SectionEnd
I understand that the "A" argument means this should APPEND the last argument to system path. However, testing this revealed that it overwrote my Path variable. Further tests reveal this is because Path was too long (>1024 chars, per the tutorial).
Is there a "safe" way to append to Path then? I am looking for a function that will append if Path is short enough, otherwise do nothing and report an error, something of that sort. I'm wondering if a standard method of doing this already exists. Thanks!
We have encountered some problems with path modifications from NSIS installers due to the fact that the default string management is limited to 1024 bytes and that string manipulations involved in path modification is truncating strings to 1024 and that is sometimes braking workstation environment (especially in development hosts where many tools are installed). BTW, There are many nsis built setups in the wild that are suffering from this problem.
We are using some different code derived from the AddToPath function from Path manipulation but the problem stays similar.
The best workaround that we are using until now is by using the special build of NSIS that provides the large string support (of 8kB instead of 1 kB). That build is available in the special builds page of the NSIS wiki.
Can you try this?
Section
ReadEnvStr $0 PATH
StrCpy $0 "$0;C:\Program Files\something"
StrLen $1 $0
${if} $1 < 1024
${EnvVarUpdate} $0 "PATH" "A" "HKLM" "C:\Program Files\something"
${else}
messagebox mb_ok "error writing environment variable"
${endIf}
SectionEnd

Include File that is not in the same directory as script

I have a NSIS script that is attempting to include a .NSI file that sits in a different folder.
My Problem: When I go to compile my script I get the compile error !include: could not find: "../Utilities.nsi". This file exists and is in the correct location I am specifying(in the parent directory - one step back).
How can I include a file that sits in another directory? I hope its possible.
!include "../Utilities.nsi" # include error: '!include: could not find: "../Utilities.nsi"'
InstallDir "abc"
Name "def"
OutFile "def.exe"
Section
DetailPrint "Hello World"
SectionEnd
The manual says this about !include:
This command will include 'file' as if it was part of the original
script. Note that if a file is included in another directory, the
current directory is still where the script was compiled from (not
where the included file resides). If the compiler can't find the file
it will look for it in every include directory. See !addincludedir for
more information. If the /nonfatal switch is used and no files are
found, a warning will be issued instead of an error."
Also, the examples in the manual do not use quotation marks -- did you try
removing them? Also, "/" => "\".

rename file with the name of installer name in NSIS installer?

I'm working with NSIS installer. I need to change file defined in install path to the same installer name.
I try to use rename function like:
Rename "$INSTDIR\app.exe" "$INSTDIR\installname.exe"
but I need the installer name automatic.
Take a look at the constants, $EXEFILE is the filename, or $EXEPATH for the full path. If you want the name attribute you used in your source file, it is $(^Name)...
From FileFunc header you can combine GetExeName and GetFileName macros to get the installer's name:
!include "FileFunc.nsh"
OutFile test.exe
section main
${GetExeName} $R0
${GetFileName} "$R0" $R1
MessageBox MB_OK "My installer's exe is $R1"
sectionend
Now you can test it yourself.

Create more than 1 uninstaller in a NSIS Section

Can a NSIS Section create more than 1 uninstaller?
My installer can install plugins for 3 different versions of an Application - therefore theres 3 different directories where the installer will install the files.
In each of those directories I want to add an uninstaller file that will remove only the files in that directory.
Each of the 3 uninstall files are created within the same Section area, is this invalid? How can I get my script to create 3 uninstallers(if possible)?
The following Section only creates one uninstaller, the last one(Version 10 uninstaller):
Section "Install Plugin Files" MainSetup
CheckInstallVers8:
IntCmp $installVers8 1 InstallVersion8 CheckInstallVers9 InstallVersion8
CheckInstallVers9:
IntCmp $installVers9 1 InstallVersion9 CheckInstallVers10 InstallVersion9
CheckInstallVers10:
IntCmp $installVers10 1 InstallVersion10 MainInstallation InstallVersion10
InstallVersion8:
# install plugins...
SetOutPath $VERS8DIR
writeUninstaller "${APPNAME} Uninstall.exe"
GoTo CheckInstallVers9
InstallVersion9:
SetOutPath $VERS9DIR
writeUninstaller "${APPNAME} Uninstall.exe"
GoTo CheckInstallVers10
InstallVersion10:
SetOutPath $VERS10DIR
writeUninstaller "${APPNAME} Uninstall.exe"
SectionEnd
You can call WriteUninstaller as many times as you want but you should use the full path name (writeUninstaller "$VERSxDIR\${APPNAME} Uninstall.exe")
You did not post a full script so it is hard to tell what is wrong with the logic (You might want to use LogicLib.nsh so you can do {IF}s) but you should be able to "MessageBox debug" your way to the solution.
One thing you did not talk about that might be relevant is the uninstaller logic. If the 3 uninstallers all do the exact same task then this is not an issue but I'd expect at least a difference in the uninstaller registry registration.
There are two ways to deal with this:
Tag data to the end of the uninstaller (or a .ini in the same directory)
Use !system to call makensis.exe and generate uninstallers at compile time that you include as normal Files
A different solution that might be relevant for plugins in sub-directories is to use a component page in the uninstaller and only delete the uninstaller when all 3 plugins have been removed...

Resources