I want to pass external .exe parameters via IP textbox and Key textbox.
This is my Setup code. The external .exe receives three parameters.
The first is the product name, the second is the ip, the third is the key.
You do not know how to write nsis to pass external parameters.
How to use is confusing.
Under Code(Setup.nsi)
## input lincesekey, ip
Function PageInputLicenseInfo
ReserveFile "pageInputLicenseInfo.ini"
!insertmacro MUI_INSTALLOPTIONS_EXTRACT "pageInputLicenseInfo.ini"
!insertmacro MUI_INSTALLOPTIONS_DISPLAY "pageInputLicenseInfo.ini"
FunctionEnd
## I want to pass external .exe parameters
Function MyCustomLicense
#IP
!insertmacro MUI_INSTALLOPTIONS_READ $R0 "pageInputLicenseInfo.ini" "Field 3" "State"
${If} $R0 == "1"
Exec '"$INSTDIR\JCertFileGenerator.exe "/${PRODUCT_NAME},$R0""'
${EndIf}
#KEY
!insertmacro MUI_INSTALLOPTIONS_READ $R1 "pageInputLicenseInfo.ini" "Field 4" "State"
${If} $R1 == "1"
Exec '"$INSTDIR\JCertFileGenerator.exe "/${PRODUCT_NAME},$R0,$R1""'
${EndIf}
## external .exe
!insertmacro MUI_INSTALLOPTIONS_READ $R2 "pageInputLicenseInfo.ini" "Field 5" "State"
${If} $R2 == "1"
File "..\ADAgent\bin\Release\JCertFileGenerator.exe"
Exec '"$INSTDIR\JCertFileGenerator.exe "/${PRODUCT_NAME},$R0,$R1""'
${EndIf}
FunctionEnd
Under Code(pageInputLicenseInfo.ini)
Ini file generated by the HM NIS Edit IO designer.
[Settings]
NumFields=5
[Field 1]
Type=Label
Text=IP
Left=6
Right=37
Top=8
Bottom=19
[Field 2]
Type=Label
Text=License Key
Left=5
Right=64
Top=24
Bottom=35
[Field 3]
Type=Text
Left=65
Right=274
Top=4
Bottom=16
State=1
[Field 4]
Type=Text
Left=65
Right=274
Top=20
Bottom=33
State=1
[Field 5]
Type=Button
Text=확인
Flags=NOTIFY
Left=225
Right=275
Top=40
Bottom=56
State=1
I would appreciate if you write a method for passing parameters to an external .exe using fields 3,4,5.
Your command-line quotes are wrong and you also fail to extract JCertFileGenerator.exe in some of the code-paths!
Quoting should look like this:
Exec '"c:\my path\program.exe" param1 "param with spaces" /param3'
And here is a silly example:
Unicode True
!define PRODUCT_NAME "Hello World"
Name "${PRODUCT_NAME}"
OutFile Test.exe
!include MUI.nsh
!include LogicLib.nsh
!include InstallOptions.nsh
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
Page Custom LicensekeyPageCreate LicensekeyPageNotify
!insertmacro MUI_LANGUAGE English
Function .onInit
; I'm writing the .ini directly here because this is just an example
InitPluginsDir
FileOpen $0 "$PluginsDir\pageInputLicenseInfo.ini" a
FileWriteUTF16LE /BOM $0 ""
FileClose $0
WriteIniStr "$PluginsDir\pageInputLicenseInfo.ini" "Settings" NumFields 5
WriteIniStr "$PluginsDir\pageInputLicenseInfo.ini" "Field 1" Type Label
WriteIniStr "$PluginsDir\pageInputLicenseInfo.ini" "Field 1" Text IP
WriteIniStr "$PluginsDir\pageInputLicenseInfo.ini" "Field 1" Left 6
WriteIniStr "$PluginsDir\pageInputLicenseInfo.ini" "Field 1" Right 37
WriteIniStr "$PluginsDir\pageInputLicenseInfo.ini" "Field 1" Top 8
WriteIniStr "$PluginsDir\pageInputLicenseInfo.ini" "Field 1" Bottom 19
WriteIniStr "$PluginsDir\pageInputLicenseInfo.ini" "Field 2" Type Label
WriteIniStr "$PluginsDir\pageInputLicenseInfo.ini" "Field 2" Text "License Key"
WriteIniStr "$PluginsDir\pageInputLicenseInfo.ini" "Field 2" Left 5
WriteIniStr "$PluginsDir\pageInputLicenseInfo.ini" "Field 2" Right 64
WriteIniStr "$PluginsDir\pageInputLicenseInfo.ini" "Field 2" Top 24
WriteIniStr "$PluginsDir\pageInputLicenseInfo.ini" "Field 2" Bottom 35
WriteIniStr "$PluginsDir\pageInputLicenseInfo.ini" "Field 3" Type Text
WriteIniStr "$PluginsDir\pageInputLicenseInfo.ini" "Field 3" Left 65
WriteIniStr "$PluginsDir\pageInputLicenseInfo.ini" "Field 3" Right 274
WriteIniStr "$PluginsDir\pageInputLicenseInfo.ini" "Field 3" Top 4
WriteIniStr "$PluginsDir\pageInputLicenseInfo.ini" "Field 3" Bottom 16
WriteIniStr "$PluginsDir\pageInputLicenseInfo.ini" "Field 3" State 1
WriteIniStr "$PluginsDir\pageInputLicenseInfo.ini" "Field 4" Type Text
WriteIniStr "$PluginsDir\pageInputLicenseInfo.ini" "Field 4" Left 65
WriteIniStr "$PluginsDir\pageInputLicenseInfo.ini" "Field 4" Right 274
WriteIniStr "$PluginsDir\pageInputLicenseInfo.ini" "Field 4" Top 20
WriteIniStr "$PluginsDir\pageInputLicenseInfo.ini" "Field 4" Bottom 33
WriteIniStr "$PluginsDir\pageInputLicenseInfo.ini" "Field 4" State 1
WriteIniStr "$PluginsDir\pageInputLicenseInfo.ini" "Field 5" Type Button
WriteIniStr "$PluginsDir\pageInputLicenseInfo.ini" "Field 5" Text "${U+d655}${U+c778}"
WriteIniStr "$PluginsDir\pageInputLicenseInfo.ini" "Field 5" Flags NOTIFY
WriteIniStr "$PluginsDir\pageInputLicenseInfo.ini" "Field 5" Left 225
WriteIniStr "$PluginsDir\pageInputLicenseInfo.ini" "Field 5" Right 275
WriteIniStr "$PluginsDir\pageInputLicenseInfo.ini" "Field 5" Top 40
WriteIniStr "$PluginsDir\pageInputLicenseInfo.ini" "Field 5" Bottom 56
WriteIniStr "$PluginsDir\pageInputLicenseInfo.ini" "Field 5" State 1
FunctionEnd
Function LicenseKeyPageCreate
!insertmacro INSTALLOPTIONS_DISPLAY "pageInputLicenseInfo.ini"
FunctionEnd
Function LicensekeyPageNotify
!insertmacro INSTALLOPTIONS_READ $0 "pageInputLicenseInfo.ini" "Settings" "State"
${If} $0 = 5 ; Was the button clicked?
!insertmacro MUI_INSTALLOPTIONS_READ $R0 "pageInputLicenseInfo.ini" "Field 3" "State"
!insertmacro MUI_INSTALLOPTIONS_READ $R1 "pageInputLicenseInfo.ini" "Field 4" "State"
ExecWait '"cmd.exe" /C echo "${PRODUCT_NAME}" IP=$R0 Key="$R1" &pause'
Abort ; Stay on the current page
${EndIf}
FunctionEnd
Executing something in $InstDir before you get to the InstFiles page is usually not a good idea, you might want to use $PluginsDir instead or ask for the license key information after the InstFiles page.
Related
Hope you guys can help me out again. I have created a custom page, and in that page are sever text fieldsa and 2 droplists. I also have a clear button that if pressed it clears all the fields on the screen.
Note: I used the code from TestNotify.nsu in examples
The issue I have is one, when pressing clear the values are written to the ini file so upon reloading the program the last Fields used populate (Even if I press clear, I have to press it twice clear the ini file)
Second is how do I reset the droplist to the default I selected when pressing reset.
So the only section I am working on now is the clearbtn, so how can i reset the droplists to a specific value, and clear data from ini when pressing clear only once.
###Add Auto Start option
SetCompressor lzma
XPStyle on
!define FolderImages "Included\Images"
!define ImageIcon "Icon.ico"
!define ImageHDR "HDR.bmp"
!define PRODUCT_NAME "Test"
!define PRODUCT_VERSION "1.0"
!define MUI_ICON ".\${FolderImages}\${ImageIcon}"
Icon ".\${FolderImages}\${ImageIcon}"
!include WinVer.nsh
!include LogicLib.nsh
!include x64.nsh
!include FileFunc.nsh
!include MUI.nsh
!include WinMessages.nsh
!include InstallOptions.nsh
!include Sections.nsh
!include nsDialogs.nsh
!define MUI_HEADERIMAGE
!define MUI_HEADERIMAGE_BITMAP ".\${FolderImages}\${ImageHDR}"
Page custom SetCustom ValidateCustom
!insertmacro MUI_LANGUAGE "English"
Function SetCustom
!insertmacro MUI_HEADER_TEXT "Licence Key Generator" "Create or Read Licence Keys"
#Hides the close button
GetDlgItem $R0 $HWNDPARENT 1
ShowWindow $R0 ${SW_HIDE}
InstallOptions::initDialog ".\UserProfiles.ini"
; In this mode InstallOptions returns the window handle so we can use it
Pop $0
; Now show the dialog and wait for it to finish
InstallOptions::show
; Finally fetch the InstallOptions status value (we don't care what it is though)
Pop $0
FunctionEnd
Function ValidateCustom
# At this point the user has either pressed cancel or one of our custom buttons
# We find out which by reading from the INI file
ReadINIStr $0 ".\UserProfiles.ini" "Settings" "State"
StrCmp $0 0 cancelbtn
StrCmp $0 19 createbtn
StrCmp $0 20 readbtn
StrCmp $0 21 comparebtn
StrCmp $0 22 clearbtn
Abort # Return to the page
createbtn:
Abort # Return to the page
readbtn:
Abort # Return to the page
comparebtn:
Abort # Return to the page
clearbtn:
#Text Field
ReadINIStr $1 ".\UserProfiles.ini" "Field 6" "HWND"
SendMessage $1 ${WM_SETTEXT} 0 "STR:"
#Text Field
ReadINIStr $1 ".\UserProfiles.ini" "Field 8" "HWND"
SendMessage $1 ${WM_SETTEXT} 0 "STR:"
#Text Field
ReadINIStr $1 ".\UserProfiles.ini" "Field 10" "HWND"
SendMessage $1 ${WM_SETTEXT} 0 "STR:"
#Drop List ------------------------------------------------------------<<<<
ReadINIStr $1 ".\UserProfiles.ini" "Field 12" "HWND"
SendMessage $1 ${WM_SETTETX} 0 "STR:"
#Text Field
ReadINIStr $1 ".\UserProfiles.ini" "Field 14" "HWND"
SendMessage $1 ${WM_SETTEXT} 0 "STR:"
#Drop List ------------------------------------------------------------<<<<
ReadINIStr $1 ".\UserProfiles.ini" "Field 16" "HWND"
SendMessage $1 ${WM_SETTEXT} 0 "STR:"
#Text Field
ReadINIStr $1 ".\UserProfiles.ini" "Field 18" "HWND"
SendMessage $1 ${WM_SETTEXT} 0 "STR:"
Abort # Return to the page
cancelbtn:
FunctionEnd
Section Dummy
SectionEnd
You can clear a droplist by sending the CB_RESETCONTENT message:
Var MyDir
Function .onInit
; Create example .ini
InitPluginsDir
StrCpy $MyDir $Temp ; Use something else in a real application, or use $PluginsDir.
WriteIniStr "$MyDir\UserProfiles.ini" "Settings" NumFields 4
WriteIniStr "$MyDir\UserProfiles.ini" "Field 1" Type Button
WriteIniStr "$MyDir\UserProfiles.ini" "Field 1" Left 0
WriteIniStr "$MyDir\UserProfiles.ini" "Field 1" Right 50
WriteIniStr "$MyDir\UserProfiles.ini" "Field 1" Top 0
WriteIniStr "$MyDir\UserProfiles.ini" "Field 1" Bottom 14
WriteIniStr "$MyDir\UserProfiles.ini" "Field 1" Text "&Clear"
WriteIniStr "$MyDir\UserProfiles.ini" "Field 1" Flags NOTIFY
WriteIniStr "$MyDir\UserProfiles.ini" "Field 2" Type Text
WriteIniStr "$MyDir\UserProfiles.ini" "Field 2" Left 0
WriteIniStr "$MyDir\UserProfiles.ini" "Field 2" Right 100
WriteIniStr "$MyDir\UserProfiles.ini" "Field 2" Top 15
WriteIniStr "$MyDir\UserProfiles.ini" "Field 2" Bottom 30
WriteIniStr "$MyDir\UserProfiles.ini" "Field 3" Type Droplist
WriteIniStr "$MyDir\UserProfiles.ini" "Field 3" Left 0
WriteIniStr "$MyDir\UserProfiles.ini" "Field 3" Right 100
WriteIniStr "$MyDir\UserProfiles.ini" "Field 3" Top 35
WriteIniStr "$MyDir\UserProfiles.ini" "Field 3" Bottom 99
WriteIniStr "$MyDir\UserProfiles.ini" "Field 4" Type Button
WriteIniStr "$MyDir\UserProfiles.ini" "Field 4" Left 55
WriteIniStr "$MyDir\UserProfiles.ini" "Field 4" Right 105
WriteIniStr "$MyDir\UserProfiles.ini" "Field 4" Top 0
WriteIniStr "$MyDir\UserProfiles.ini" "Field 4" Bottom 14
WriteIniStr "$MyDir\UserProfiles.ini" "Field 4" Text "&Add"
WriteIniStr "$MyDir\UserProfiles.ini" "Field 4" Flags NOTIFY
FunctionEnd
Function SetCustom
InstallOptions::initDialog "$MyDir\UserProfiles.ini"
; In this mode InstallOptions returns the window handle so we can use it
Pop $0
; Now show the dialog and wait for it to finish
InstallOptions::show
; Finally fetch the InstallOptions status value (we don't care what it is though)
Pop $0
FunctionEnd
Function ValidateCustom
# At this point the user has either pressed cancel or one of our custom buttons
# We find out which by reading from the INI file
ReadINIStr $0 "$MyDir\UserProfiles.ini" "Settings" "State"
StrCmp $0 1 clearbtn
StrCmp $0 4 addbtn
Abort # Return to the page
clearbtn:
#Text Field
ReadINIStr $1 "$MyDir\UserProfiles.ini" "Field 2" "HWND"
SendMessage $1 ${WM_SETTEXT} 0 "STR:"
#Droplist Field
ReadINIStr $2 "$MyDir\UserProfiles.ini" "Field 3" "HWND"
SendMessage $2 ${CB_RESETCONTENT} 0 0
DeleteIniStr "$MyDir\UserProfiles.ini" "Field 3" "ListItems"
DeleteIniStr "$MyDir\UserProfiles.ini" "Field 3" "State"
Abort # Return to the page
addbtn:
ReadINIStr $1 "$MyDir\UserProfiles.ini" "Field 2" "State"
ReadINIStr $2 "$MyDir\UserProfiles.ini" "Field 3" "HWND"
SendMessage $2 ${CB_ADDSTRING} 0 "STR:$1"
SendMessage $2 ${CB_SELECTSTRING} 0 "STR:$1"
Abort # Return to the page
FunctionEnd
You should not use relative .INI paths, that is just asking for trouble, use full paths!
I am new for nsis
Created ini page which contains "Text" type, using this type i was showing the some dynamic data in the label. The size of file is 2 kb, so i need to increase the size for "State" option in "Text" type. So how to increase the size of State using writeinistr?
To bypass the NSIS string length limitation you have to call the Windows API directly:
Page Custom MyPage
Page InstFiles
!macro IniWriteAsciiStringPtr ini sec name strptr
!if "${NSIS_CHAR_SIZE}" > 1
Push $0
Push $1
Push $2
Push "${ini}"
Push "${name}"
Push "${sec}"
StrCpy $0 ${strptr}
System::Call 'kernel32::MultiByteToWideChar(i0, i0, i$0, i-1, i0, i0)i.r2'
System::Call '*(&w$2)i.r1'
System::Call 'kernel32::MultiByteToWideChar(i0, i0, i$0, i-1, ir1, ir2)'
System::Call 'kernel32::WritePrivateProfileString(t s, t s, ir1, t s)'
System::Free $1
Pop $2
Pop $1
Pop $0
!else
System::Call 'kernel32::WritePrivateProfileString(t "${sec}", t "${name}", i ${strptr}, t "${ini}")'
!endif
!macroend
!include InstallOptions.nsh
Function MyPage
InitPluginsDir
; Building the entire .ini at run-time in this example
WriteIniStr "$PluginsDir\io.ini" Settings NumFields 1
WriteIniStr "$PluginsDir\io.ini" "Field 1" Type Text
WriteIniStr "$PluginsDir\io.ini" "Field 1" Left 1
WriteIniStr "$PluginsDir\io.ini" "Field 1" Right -2
WriteIniStr "$PluginsDir\io.ini" "Field 1" Top 5
WriteIniStr "$PluginsDir\io.ini" "Field 1" Bottom -10
WriteIniStr "$PluginsDir\io.ini" "Field 1" Flags MULTILINE
FileOpen $0 "$PluginsDir\test.txt" r
FileSeek $0 0 END $1
FileSeek $0 0 SET
System::Call '*(&i$1,i0)i.r2'
System::Call 'kernel32::ReadFile(ir0,ir2,ir1,*i,i0)'
!insertmacro IniWriteAsciiStringPtr "$PluginsDir\io.ini" "Field 1" "State" $2
System::Free $2
FileClose $0
!insertmacro INSTALLOPTIONS_DISPLAY "io.ini"
FunctionEnd
Function .onInit
InitPluginsDir
; Create a big file for this example
FileOpen $0 "$PluginsDir\test.txt" w
StrCpy $2 0
loop:
StrCmp $2 2048 done
IntOp $1 $2 % 10
StrCmp $2 2047 0 +2
StrCpy $1 "!"
FileWrite $0 $1
IntOp $2 $2 + 1
Goto loop
done:
FileClose $0
FunctionEnd
You can also bypass the .ini and set it directly in the dialog:
Page Custom MyPage
Page InstFiles
!include InstallOptions.nsh
!include WinMessages.nsh
Function MyPage
InitPluginsDir
; Building the entire .ini at run-time in this example
WriteIniStr "$PluginsDir\io.ini" Settings NumFields 1
WriteIniStr "$PluginsDir\io.ini" "Field 1" Type Text
WriteIniStr "$PluginsDir\io.ini" "Field 1" Left 1
WriteIniStr "$PluginsDir\io.ini" "Field 1" Right -2
WriteIniStr "$PluginsDir\io.ini" "Field 1" Top 5
WriteIniStr "$PluginsDir\io.ini" "Field 1" Bottom -10
WriteIniStr "$PluginsDir\io.ini" "Field 1" Flags MULTILINE
FileOpen $0 "$PluginsDir\test.txt" r
FileSeek $0 0 END $1
FileSeek $0 0 SET
System::Call '*(&i$1,i0)i.r2'
System::Call 'kernel32::ReadFile(ir0,ir2,ir1,*i,i0)'
FileClose $0
!insertmacro INSTALLOPTIONS_INITDIALOG "io.ini"
Pop $0
!insertmacro INSTALLOPTIONS_READ $0 "io.ini" "Field 1" "HWND"
!if "${NSIS_CHAR_SIZE}" > 1
!error TODO
!else
SendMessage $0 ${WM_SETTEXT} 0 $2
!endif
System::Free $2
!insertmacro INSTALLOPTIONS_SHOW
FunctionEnd
Function .onInit
InitPluginsDir
; Create a big file for this example
FileOpen $0 "$PluginsDir\test.txt" w
StrCpy $2 0
loop:
StrCmp $2 2048 done
IntOp $1 $2 % 10
StrCmp $2 2047 0 +2
StrCpy $1 "!"
FileWrite $0 $1
IntOp $2 $2 + 1
Goto loop
done:
FileClose $0
FunctionEnd
I'm attempting to create an installer that asks the user a series of questions to decide which components to install. Each choice (potentially) influences the available options in later choices (else I would just do a normal components page—I don't want to give the user invalid options).
How do I accomplish such a thing? If I just use the components page, all the options are shown, some combinations of which are completely invalid. I don't want to let the user select those. Is it possible to leave out the components page?
Here's a minimal working example of what I'm trying. (Sorry it's long, I couldn't really simplify the dialog code.)
!include nsDialogs.nsh
!include Sections.nsh
Name "mwe"
OutFile "mwe.exe"
InstallDir C:\mwe
Var hwnd
Var Level1Opt
Page custom SelectLevel1Opt ProcessLevel1
Function SelectLevel1Opt
nsDialogs::Create 1018
pop $hwnd
${NSD_CreateLabel} 0 0 100% 12u "Please select level 1 option"
Pop $hwnd
${NSD_CreateRadioButton} 10% 12u 100% 12u "Level 1 A"
Pop $hwnd
nsDialogs::SetUserData $hwnd "Level 1 A"
${NSD_OnClick} $hwnd SetLevel1
${NSD_CreateRadioButton} 10% 24u 100% 12u "Level 1 B"
Pop $hwnd
nsDialogs::SetUserData $hwnd "Level 1 B"
${NSD_OnClick} $hwnd SetLevel1
nsDialogs::Show
FunctionEnd
Function SetLevel1
Pop $hwnd
nsDialogs::GetUserData $hwnd
Pop $Level1Opt
MessageBox MB_OK "Selected: $Level1Opt"
FunctionEnd
Function ProcessLevel1
${If} $Level1Opt == "Level 1 A"
!insertmacro SelectSection Level1A
${ElseIf} $Level1Opt == "Level 1 B"
!insertmacro SelectSection Level1B
${EndIf}
FunctionEnd
Page directory
Page instfiles
Section ""
MessageBox MB_OK "Common Install"
SectionEnd
Section /o "" Level1A
MessageBox MB_OK "Level 1 A"
SectionEnd
Section /o "" Level1B
MessageBox MB_OK "Level 1 B"
SectionEnd
No matter what I choose, neither Level1A nor Level1B sections get run. The selection from the dialog is correctly detected in the handler and the post function. However, selecting the sections isn't causing them to run. Even if I add a components page, neither of them is selected.
I looked in Selection.nsh, and the example it refers to (one-section.nsi) doesn't really do what I want, because it uses the components page. (I also don't understand quite how it works.)
What am I doing wrong? In what way am I misunderstanding the way NSIS is supposed to work?
As idleberg says, the correct syntax is !insertmacro SelectSection ${Level1A} but you get a warning because the section id is not defined until after its Section instruction in your .nsi. You need to move the functions that use ${Level1A} below the sections in your source code:
!include nsDialogs.nsh
!include Sections.nsh
Page custom SelectLevel1Opt ProcessLevel1
Page instfiles
Section ""
MessageBox MB_OK "Common Install"
SectionEnd
Section /o "a" Level1A
MessageBox MB_OK "Level 1 A"
SectionEnd
Section /o "b" Level1B
MessageBox MB_OK "Level 1 B"
SectionEnd
Var hInnerDialog
Var hL1A
Var hL1B
Function SelectLevel1Opt
nsDialogs::Create 1018
pop $hInnerDialog
${NSD_CreateLabel} 0 0 100% 12u "Please select level 1 option"
Pop $0
${NSD_CreateRadioButton} 10% 12u 100% 12u "Level 1 A"
Pop $hL1A
nsDialogs::SetUserData $hL1A ${Level1A} ; Only used by the generic function
${NSD_CreateRadioButton} 10% 24u 100% 12u "Level 1 B"
Pop $hL1B
nsDialogs::SetUserData $hL1B ${Level1B} ; Only used by the generic function
nsDialogs::Show
FunctionEnd
Function ProcessLevel1
${NSD_GetState} $hL1A $1
${If} $1 <> ${BST_UNCHECKED}
!insertmacro SelectSection ${Level1A}
!insertmacro UnselectSection ${Level1B}
${Else}
!insertmacro SelectSection ${Level1B}
!insertmacro UnselectSection ${Level1A}
${EndIf}
FunctionEnd
The ProcessLevel1 function can also be implemented as a loop if there are many radio buttons:
Function ProcessLevel1
StrCpy $0 ""
loop:
FindWindow $0 "${__NSD_RadioButton_CLASS}" "" $hInnerDialog $0
System::Call "USER32::GetWindowLong(p$0,i${GWL_STYLE})i.r1"
IntOp $1 $1 & ${BS_AUTORADIOBUTTON}
${If} $1 = ${BS_AUTORADIOBUTTON} ; Is it a auto radio button?
nsDialogs::GetUserData $0 ; Get the section id
Pop $2
${NSD_GetState} $0 $1
${If} $1 <> ${BST_UNCHECKED}
!insertmacro SelectSection $2
${Else}
!insertmacro UnselectSection $2
${EndIf}
${EndIf}
IntCmp $0 0 "" loop loop
FunctionEnd
I have this Custom Page in my code, where there is a droplist with the available drives on the computer. When the user chooses the drive he wants, a .txt file is created where is written that drive (example: E:).
When you open the custom page, the drive that appear on the droplist is "C:\". But if I hit "next" without clicking on the droplist, the .txt file is not created. Even if I want C:\ and it's already there, I have to go there and click to make it work. If I don't click on the droplist before hiting "next", nothing happen.
Anybody knows why? The code is down below:
!include "MUI2.nsh"
!include FileFunc.nsh
!insertmacro GetDrives
var newCheckBox
!define NOME "S-Monitor"
Name "${NOME}"
OutFile "${NOME}.exe"
InstallDir "C:\${NOME}"
ShowInstDetails show
AllowRootDirInstall true
;--- Paginas ---
!define MUI_ICON Labels\SetupICO.ico
!define MUI_HEADERIMAGE
!define MUI_HEADERIMAGE_RIGHT
!define MUI_HEADERIMAGE_BITMAP Labels\Header.bmp
!define MUI_WELCOMEFINISHPAGE_BITMAP Labels\Left.bmp
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
Page Custom CustomCreate CustomLeave
!define MUI_FINISHPAGE_NOAUTOCLOSE
!define MUI_FINISHPAGE_RUN
!define MUI_FINISHPAGE_RUN_CHECKED
!define MUI_FINISHPAGE_RUN_TEXT "Criar atalho na Área de Trabalho"
!define MUI_FINISHPAGE_RUN_FUNCTION "AtalhoDesktop"
!define MUI_PAGE_CUSTOMFUNCTION_SHOW showNewCheckbox
!define MUI_PAGE_CUSTOMFUNCTION_LEAVE launchNewLink
!insertmacro MUI_PAGE_FINISH
;--- Idiomas ---
!insertmacro MUI_LANGUAGE "Portuguese"
!insertmacro MUI_LANGUAGE "English"
!insertmacro MUI_LANGUAGE "Spanish"
Function .onInit
!insertmacro MUI_LANGDLL_DISPLAY
InitPluginsDir
GetTempFileName $0
Rename $0 '$PLUGINSDIR\custom.ini'
FunctionEnd
;--------------------------------
;Arquivos a serem instalados
Section "Instalacao"
SetShellVarContext all
SetOutPath "$INSTDIR"
File /r Ficheiros\*.* ; LOCALIZACAO DA APLICACAO DO S-MONITOR
MessageBox MB_OK "O software BDE (Borland Database Engine) será instalado agora"
ExecWait "$INSTDIR\bde_install_Win7_32_e_64.exe"
FileOpen $1 '$INSTDIR\S-monitor.cpy' w
FileWrite $1 "CPY Location=C:\S-Monitor.cpy"
FileClose $1
writeUninstaller $INSTDIR\uninstall.exe
SectionEnd
Section "Uninstall"
MessageBox MB_YESNO "Deseja desinstalar o S-Monitor?" IDYES true IDNO false
true:
SetShellVarContext all
delete $INSTDIR\uninstall.exe
RMDir /R /REBOOTOK $INSTDIR
Goto +2
false:
MessageBox MB_OK "Desinstalação cancelada."
SectionEnd
Function AtalhoDesktop
createShortCut "$DESKTOP\S-Monitor.lnk" "C:\SMonitor.exe"
FunctionEnd
Function showNewCheckbox
${NSD_CreateCheckbox} 120u 110u 100% 10u "&Iniciar o S-Monitor ao terminar a instalação"
Pop $newCheckBox
FunctionEnd
Function launchNewLink
${NSD_GetState} $newCheckBox $0
${If} $0 <> 0
Exec "C:\S-Monitor\Smonitor.exe"
${EndIf}
FunctionEnd
Function CustomCreate
WriteIniStr '$PLUGINSDIR\custom.ini' 'Settings' 'NumFields' '6'
WriteIniStr '$PLUGINSDIR\custom.ini' 'Field 1' 'Type' 'Label'
WriteIniStr '$PLUGINSDIR\custom.ini' 'Field 1' 'Left' '5'
WriteIniStr '$PLUGINSDIR\custom.ini' 'Field 1' 'Top' '5'
WriteIniStr '$PLUGINSDIR\custom.ini' 'Field 1' 'Right' '-6'
WriteIniStr '$PLUGINSDIR\custom.ini' 'Field 1' 'Bottom' '60'
WriteIniStr '$PLUGINSDIR\custom.ini' 'Field 1' 'Text' \
'Escolha a que disco rígido quer associar a sua licença do S-Monitor.\nA instalação do S-Monitor ficará associada de forma permanente ao disco escolhido.\n\nSe desejar transferir a sua licença para outro PC mais tarde, deverá escolher um disco amovível neste passo.\nSe não sabe que opção escolher, deixe seleccionada a opção por defeito.'
StrCpy $R2 0
StrCpy $R0 ''
${GetDrives} "HDD+FDD" GetDrivesCallBack
WriteIniStr '$PLUGINSDIR\custom.ini' 'Field 2' 'Type' 'DropList'
WriteIniStr '$PLUGINSDIR\custom.ini' 'Field 2' 'Left' '30'
WriteIniStr '$PLUGINSDIR\custom.ini' 'Field 2' 'Top' '64'
WriteIniStr '$PLUGINSDIR\custom.ini' 'Field 2' 'Right' '-31'
WriteIniStr '$PLUGINSDIR\custom.ini' 'Field 2' 'Bottom' '200'
WriteIniStr '$PLUGINSDIR\custom.ini' 'Field 2' 'Flags' 'Notify'
WriteIniStr '$PLUGINSDIR\custom.ini' 'Field 2' 'State' '$R1'
WriteIniStr '$PLUGINSDIR\custom.ini' 'Field 2' 'ListItems' '$R0'
push $0
InstallOptions::Dialog '$PLUGINSDIR\custom.ini'
pop $0
pop $0
FunctionEnd
Function CustomLeave
ReadIniStr $0 '$PLUGINSDIR\custom.ini' 'Settings' 'State'
StrCmp $0 '2' 0 next
ReadIniStr $0 '$PLUGINSDIR\custom.ini' 'Field 2' 'State'
strcpy $R0 $0
StrCpy $0 $0 3
FileOpen $1 '$INSTDIR\S-monitor.cpy' w
FileWrite $1 "CPY Location=$R0S-Monitor.cpy"
FileClose $1
Abort
next:
ReadIniStr $0 '$PLUGINSDIR\custom.ini' 'Field 2' 'State'
StrCpy '$INSTDIR' '$0'
FunctionEnd
Function GetDrivesCallBack
StrCmp $R2 '0' 0 next
StrCpy $R3 '$R4'
StrCpy $R1 '$9'
IntOp $R2 $R2 + 1
next:
StrCpy $R0 '$R0$9|'
Push $0
FunctionEnd
I'm a newbie to NSIS and was wondering how $PROGRAMFILES gets the value. I know:
In a 32-bit windows,
$PROGRAMFILES: represents C:\Program Files
and
In 64-bit windows,
$PROGRAMFILES, $PROGRAMFILES32: represents C:\Program Files (x86)
where as, $PROGRAMFILES64: represents C:\Program Files
My question is, are these the constants set in NSIS or these are values read from Windows environment variable??
Thanks in advance.
They are read from the registry (The other shell constants come from SHGetSpecialFolderLocation but the programfiles csidl is buggy IIRC)
I modified this NSIS Constants script a little bit to allow support for showing the correct environment variables available to both 32-bit and 64-bit machines. Just compile this script, execute, and view the supplied INI for for all available constants specific to your version of windows.
NSIS Constants
WindowIcon Off
SilentInstall Silent
AutoCloseWindow True
Name "NSIS Constants"
OutFile "NSIS_Constants.exe"
!define DISABLEREDIR `kernel32::Wow64EnableWow64FsRedirection(i0)`
!define ENABLEREDIR `kernel32::Wow64EnableWow64FsRedirection(i1)`
Var VER
Section "Main"
ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion
StrCpy $VER $0
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "Windows" "Version" "$VER"
SetRegView 64
ReadRegStr $R0 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion" CommonFilesDir
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$COMMONFILES" "64bit COMMONFILES" "$R0"
SetRegView 32
ReadRegStr $R0 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion" CommonFilesDir
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$COMMONFILES" "32bit COMMONFILES" "$R0"
SetRegView 64
ReadRegStr $R0 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion" ProgramFilesDir
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$PROGRAMFILES" "64bit PROGRAMFILES" "$R0"
SetRegView 32
ReadRegStr $R0 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion" ProgramFilesDir
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$PROGRAMFILES" "32bit PROGRAMFILES" "$R0"
System::Call `${DISABLEREDIR}`
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$SYSDIR" "64bit SYSDIR" "$SYSDIR"
System::Call `${ENABLEREDIR}`
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$SYSDIR" "32bit SYSDIR" "$SYSDIR"
SetShellVarContext current
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$ADMINTOOLS" "current ADMINTOOLS" "$ADMINTOOLS"
SetShellVarContext all
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$ADMINTOOLS" "all ADMINTOOLS" "$ADMINTOOLS"
SetShellVarContext current
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$APPDATA" "current APPDATA" "$APPDATA"
SetShellVarContext all
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$APPDATA" "all APPDATA" "$APPDATA"
SetShellVarContext current
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$CDBURN_AREA" "current CDBURN_AREA" "$CDBURN_AREA"
SetShellVarContext all
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$CDBURN_AREA" "all CDBURN_AREA" "$CDBURN_AREA"
SetShellVarContext current
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$CMDLINE" "current CMDLINE" "$CMDLINE"
SetShellVarContext all
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$CMDLINE" "all CMDLINE" "$CMDLINE"
SetShellVarContext current
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$COMMONFILES" "current COMMONFILES" "$COMMONFILES"
SetShellVarContext all
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$COMMONFILES" "all COMMONFILES" "$COMMONFILES"
SetShellVarContext current
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$COOKIES" "current COOKIES" "$COOKIES"
SetShellVarContext all
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$COOKIES" "all COOKIES" "$COOKIES"
SetShellVarContext current
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$DESKTOP" "current DESKTOP" "$DESKTOP"
SetShellVarContext all
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$DESKTOP" "all DESKTOP" "$DESKTOP"
SetShellVarContext current
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$DOCUMENTS" "current DOCUMENTS" "$DOCUMENTS"
SetShellVarContext all
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$DOCUMENTS" "all DOCUMENTS" "$DOCUMENTS"
SetShellVarContext current
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$EXEDIR" "current EXEDIR" "$EXEDIR"
SetShellVarContext all
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$EXEDIR" "all EXEDIR" "$EXEDIR"
SetShellVarContext current
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$FAVORITES" "current FAVORITES" "$FAVORITES"
SetShellVarContext all
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$FAVORITES" "all FAVORITES" "$FAVORITES"
SetShellVarContext current
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$FONTS" "current FONTS" "$FONTS"
SetShellVarContext all
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$FONTS" "all FONTS" "$FONTS"
SetShellVarContext current
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$HISTORY" "current HISTORY" "$HISTORY"
SetShellVarContext all
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$HISTORY" "all HISTORY" "$HISTORY"
SetShellVarContext current
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$HWNDPARENT" "current HWNDPARENT" "$HWNDPARENT"
SetShellVarContext all
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$HWNDPARENT" "all HWNDPARENT" "$HWNDPARENT"
SetShellVarContext current
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$INSTDIR" "current INSTDIR" "$INSTDIR"
SetShellVarContext all
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$INSTDIR" "all INSTDIR" "$INSTDIR"
SetShellVarContext current
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$INTERNET_CACHE" "current INTERNET_CACHE" "$INTERNET_CACHE"
SetShellVarContext all
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$INTERNET_CACHE" "all INTERNET_CACHE" "$INTERNET_CACHE"
SetShellVarContext current
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$LANGUAGE" "current LANGUAGE" "$LANGUAGE"
SetShellVarContext all
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$LANGUAGE" "all LANGUAGE" "$LANGUAGE"
SetShellVarContext current
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$LOCALAPPDATA" "current LOCALAPPDATA" "$LOCALAPPDATA"
SetShellVarContext all
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$LOCALAPPDATA" "all LOCALAPPDATA" "$LOCALAPPDATA"
SetShellVarContext current
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$MUSIC" "current MUSIC" "$MUSIC"
SetShellVarContext all
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$MUSIC" "all MUSIC" "$MUSIC"
SetShellVarContext current
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$NETHOOD" "current NETHOOD" "$NETHOOD"
SetShellVarContext all
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$NETHOOD" "all NETHOOD" "$NETHOOD"
SetShellVarContext current
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$OUTDIR" "current OUTDIR" "$OUTDIR"
SetShellVarContext all
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$OUTDIR" "all OUTDIR" "$OUTDIR"
SetShellVarContext current
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$PICTURES" "current PICTURES" "$PICTURES"
SetShellVarContext all
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$PICTURES" "all PICTURES" "$PICTURES"
SetShellVarContext current
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$PLUGINSDIR" "current PLUGINSDIR" "$PLUGINSDIR"
SetShellVarContext all
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$PLUGINSDIR" "all PLUGINSDIR" "$PLUGINSDIR"
SetShellVarContext current
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$PRINTHOOD" "current PRINTHOOD" "$PRINTHOOD"
SetShellVarContext all
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$PRINTHOOD" "all PRINTHOOD" "$PRINTHOOD"
SetShellVarContext current
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$PROFILE" "current PROFILE" "$PROFILE"
SetShellVarContext all
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$PROFILE" "all PROFILE" "$PROFILE"
SetShellVarContext current
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$PROGRAMFILES" "current PROGRAMFILES" "$PROGRAMFILES"
SetShellVarContext all
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$PROGRAMFILES" "all PROGRAMFILES" "$PROGRAMFILES"
SetShellVarContext current
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$QUICKLAUNCH" "current QUICKLAUNCH" "$QUICKLAUNCH"
SetShellVarContext all
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$QUICKLAUNCH" "all QUICKLAUNCH" "$QUICKLAUNCH"
SetShellVarContext current
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$RECENT" "current RECENT" "$RECENT"
SetShellVarContext all
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$RECENT" "all RECENT" "$RECENT"
SetShellVarContext current
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$RESOURCES" "current RESOURCES" "$RESOURCES"
SetShellVarContext all
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$RESOURCES" "all RESOURCES" "$RESOURCES"
SetShellVarContext current
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$RESOURCES_LOCALIZED" "current RESOURCES_LOCALIZED" "$RESOURCES_LOCALIZED"
SetShellVarContext all
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$RESOURCES_LOCALIZED" "all RESOURCES_LOCALIZED" "$RESOURCES_LOCALIZED"
SetShellVarContext current
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$SENDTO" "current SENDTO" "$SENDTO"
SetShellVarContext all
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$SENDTO" "all SENDTO" "$SENDTO"
SetShellVarContext current
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$SMPROGRAMS" "current SMPROGRAMS" "$SMPROGRAMS"
SetShellVarContext all
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$SMPROGRAMS" "all SMPROGRAMS" "$SMPROGRAMS"
SetShellVarContext current
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$SMSTARTUP" "current SMSTARTUP" "$SMSTARTUP"
SetShellVarContext all
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$SMSTARTUP" "all SMSTARTUP" "$SMSTARTUP"
SetShellVarContext current
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$STARTMENU" "current STARTMENU" "$STARTMENU"
SetShellVarContext all
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$STARTMENU" "all STARTMENU" "$STARTMENU"
SetShellVarContext current
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$SYSDIR" "current SYSDIR" "$SYSDIR"
SetShellVarContext all
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$SYSDIR" "all SYSDIR" "$SYSDIR"
SetShellVarContext current
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$TEMP" "current TEMP" "$TEMP"
SetShellVarContext all
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$TEMP" "all TEMP" "$TEMP"
SetShellVarContext current
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$TEMPLATES" "current TEMPLATES" "$TEMPLATES"
SetShellVarContext all
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$TEMPLATES" "all TEMPLATES" "$TEMPLATES"
SetShellVarContext current
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$VIDEOS" "current VIDEOS" "$VIDEOS"
SetShellVarContext all
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$VIDEOS" "all VIDEOS" "$VIDEOS"
SetShellVarContext current
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$WINDIR" "current WINDIR" "$WINDIR"
SetShellVarContext all
WriteINIStr $EXEDIR\Windows_$VER_Constants.ini "$$WINDIR" "all WINDIR" "$WINDIR"
MessageBox MB_USERICON "NSIS Constants for this computer are in Windows_$VER_Constants.ini"
SectionEnd
When executed it should output something similar to the following. These values or for a 64-bit Windows 8.1..
[Windows]
Version=6.3
[$APPDATA]
current APPDATA=C:\Users\Devin\AppData\Roaming
all APPDATA=C:\ProgramData
[$COMMONFILES]
current COMMONFILES=C:\Program Files (x86)\Common Files
all COMMONFILES=C:\Program Files (x86)\Common Files
64bit COMMONFILES=C:\Program Files\Common Files
32bit COMMONFILES=C:\Program Files (x86)\Common Files
[$DESKTOP]
current DESKTOP=C:\Users\Devin\Desktop
all DESKTOP=C:\Users\Public\Desktop
[$DOCUMENTS]
current DOCUMENTS=C:\Users\Devin\Documents
all DOCUMENTS=C:\Users\Public\Documents
[$PROGRAMFILES]
current PROGRAMFILES=C:\Program Files (x86)
all PROGRAMFILES=C:\Program Files (x86)
64bit PROGRAMFILES=C:\Program Files
32bit PROGRAMFILES=C:\Program Files (x86)
[$SYSDIR]
current SYSDIR=C:\Windows\system32
all SYSDIR=C:\Windows\system32
64bit SYSDIR=C:\Windows\system32
32bit SYSDIR=C:\Windows\system32
There is plenty more given. This is just an example of what this script will output. Hope this helps. =)