Reputation: 297
I'm building an installer with NSIS to help me deploy cgminer to a bunch of computers in my basement. The installer asks for two things:
The installer uses the user provided pool URL, login name, and password to generate a simple cgminer config file.
Here's the code that writes the JSON config file:
FileOpen $9 $INSTDIR\config.conf w ;Opens a Empty File for writing
FileWrite $9 "{$\r$\n"
FileWrite $9 "$\"pools$\" : [$\r$\n"
FileWrite $9 "$\t{$\r$\n"
FileWrite $9 "$\t$\t$\"url$\" : $\"$POOL$\",$\r$\n"
FileWrite $9 "$\t$\t$\"user$\" : $\"$USER$\",$\r$\n"
FileWrite $9 "$\t$\t$\"pass$\" : $\"$PASS$\",$\r$\n"
FileWrite $9 "$\t}$\r$\n"
FileWrite $9 "],$\r$\n"
FileWrite $9 "$\r$\n"
FileWrite $9 "$\"intensity$\" : $\"d$\"$\r$\n"
FileWrite $9 "}$\r$\n"
FileClose $9 ; closes the file
This is what I'm expecting:
{
"pools" : [
{
"url" : "http://bc.minercity.org:4583",
"user" : "fizzlefazzle_miner",
"pass" : "rosebud",
}
],
"intensity" : "d"
}
However this is what I get:
{
"pools" : [
{
"url" : "1639776",
"user" : "1115594",
"pass" : "1115614",
}
],
"intensity" : "d"
}
I'm assuming I'm getting memory addresses instead of the strings I entered. Here is the code in it's entirety:
; bitcoinminer.nsi
;
; sets up a basic bitcoin miner.
; asks user for mining pool and user/pass
; installs cgminer to <OS DRIVE>\Documents and Settings\<CURRENT USER>\Local Settings\Application Data\ccc\bitcoin\cgminer
; generates cgminer config file and puts it in above dir
;
;--------------------------------
; Includes
!include nsDialogs.nsh
!include LogicLib.nsh
;--------------------------------
; The name of the installer
Name "Bitcoin Miner"
OutFile BitcoinMiner.exe
; The default installation directory
InstallDir "$PROFILE\Local Settings\Application Data\ccc\bitcoin\cgminer2"
; Request application privileges for Windows Vista
RequestExecutionLevel user
;--------------------------------
; Pages
Page Custom poolPageCreate poolPageLeave
Page directory
Page instfiles
Var POOL
Var USER
Var PASS
Function poolPageCreate
nsDialogs::Create 1018 ; creates a new dialog and returns it's HWND on the stack
Pop $0 ; HWID of new dialog stored to $0
${NSD_CreateLabel} 0 0u 75% 12u "Pool URL (ex: http://bc.minercity.org:6347)" ; create label. HWND on the stack
Pop $0 ; HWID of new label stored to $0
${NSD_CreateText} 0 13u 100% 12u 'http://bc.minercity.org:6347'
Pop $POOL
GetFunctionAddress $0 poolChange
nsDialogs::OnChange $POOL $0
${NSD_CreateLabel} 0 40u 75% 12u "Login name (ex: fizzlefazzle_miner)"
Pop $0
${NSD_CreateText} 0 53u 100% 12u 'fizzlefazzle_miner'
Pop $USER
GetFunctionAddress $0 userChange
nsDialogs::OnChange $USER $0
${NSD_CreateLabel} 0 77u 75% 12u "Password (ex: rosebud)"
Pop $0
${NSD_CreateText} 0 90u 100% 12u 'rosebud'
Pop $PASS
GetFunctionAddress $0 passChange
nsDialogs::OnChange $PASS $0
nsDialogs::Show
FunctionEnd
Function poolPageLeave
FunctionEnd
Function poolChange
Pop $0 # HWND
System::Call user32::GetWindowText(i$POOL,t.r0,i${NSIS_MAX_STRLEN})
FunctionEnd
Function userChange
Pop $0
System::Call user32::GetWindowText(i$USER,t.r0,i${NSIS_MAX_STRLEN})
FunctionEnd
Function passChange
Pop $0
System::Call user32::GetWindowText(i$PASS,t.r0,i${NSIS_MAX_STRLEN})
FunctionEnd
Section
;--------------------------------
; The stuff to install
; Set output path to the installation directory.
SetOutPath $INSTDIR
; Put file there
File /r "cgminer\"
FileOpen $9 $INSTDIR\config.conf w ;Opens a Empty File for writing
FileWrite $9 "{$\r$\n"
FileWrite $9 "$\"pools$\" : [$\r$\n"
FileWrite $9 "$\t{$\r$\n"
FileWrite $9 "$\t$\t$\"url$\" : $\"$POOL$\",$\r$\n"
FileWrite $9 "$\t$\t$\"user$\" : $\"$USER$\",$\r$\n"
FileWrite $9 "$\t$\t$\"pass$\" : $\"$PASS$\",$\r$\n"
FileWrite $9 "$\t}$\r$\n"
FileWrite $9 "],$\r$\n"
FileWrite $9 "$\r$\n"
FileWrite $9 "$\"intensity$\" : $\"d$\"$\r$\n"
FileWrite $9 "}$\r$\n"
FileClose $9 ; closes the file
SectionEnd
What am I doing wrong?
Upvotes: 0
Views: 3341
Reputation: 11465
There is no problem with string interpolation. Your problem is with the handling of the edit texts: when you state e.g.
${NSD_CreateText} 0 13u 100% 12u 'http://bc.minercity.org:6347'
Pop $POOL
GetFunctionAddress $0 poolChange
nsDialogs::OnChange $POOL $0
You correctly create an edit text and keep its handle to use in the defined callback. But later
FileWrite $9 "$\t$\t$\"url$\" : $\"$POOL$\",$\r$\n"
The file write will store the control handle in the file and not its content.
Also there are some problems with the callbacks:
$0
register, thus $0
would contain the text of the last modified fieldI would use 3 variables for the edit handles and another 3 for the values, then read the value in the page leave callback. Also you can delete the 3 callbacks if you just want to get the final value and not want to react to a value change:
!include nsDialogs.nsh
!include LogicLib.nsh
Name "Bitcoin Miner"
OutFile BitcoinMiner.exe
RequestExecutionLevel user
Page Custom poolPageCreate poolPageLeave
Page directory
Page instfiles
Var POOLHDL
Var USERHDL
Var PASSHDL
Var POOL
Var USER
Var PASS
Function poolPageCreate
nsDialogs::Create 1018 ; creates a new dialog and returns it's HWND on the stack
Pop $0 ; HWID of new dialog stored to $0
${NSD_CreateLabel} 0 0u 75% 12u "Pool URL (ex: http://bc.minercity.org:6347)" ; create label. HWND on the stack
Pop $0 ; HWID of new label stored to $0
${NSD_CreateText} 0 13u 100% 12u 'http://bc.minercity.org:6347'
Pop $POOLHDL
${NSD_CreateLabel} 0 40u 75% 12u "Login name (ex: fizzlefazzle_miner)"
Pop $0
${NSD_CreateText} 0 53u 100% 12u 'fizzlefazzle_miner'
Pop $USERHDL
${NSD_CreateLabel} 0 77u 75% 12u "Password (ex: rosebud)"
Pop $0
${NSD_CreateText} 0 90u 100% 12u 'rosebud'
Pop $PASSHDL
nsDialogs::Show
FunctionEnd
Function poolPageLeave
${NSD_GetText} $POOLHDL $POOL
${NSD_GetText} $USERHDL $USER
${NSD_GetText} $PASSHDL $PASS
FunctionEnd
Section
SetOutPath $INSTDIR
File /r "cgminer\"
FileOpen $9 $EXEDIR\config.conf w ;Opens a Empty File for writing
FileWrite $9 "{$\r$\n"
FileWrite $9 "$\"pools$\" : [$\r$\n"
FileWrite $9 "$\t{$\r$\n"
FileWrite $9 "$\t$\t$\"url$\" : $\"$POOL$\",$\r$\n"
FileWrite $9 "$\t$\t$\"user$\" : $\"$USER$\",$\r$\n"
FileWrite $9 "$\t$\t$\"pass$\" : $\"$PASS$\",$\r$\n"
FileWrite $9 "$\t}$\r$\n"
FileWrite $9 "],$\r$\n"
FileWrite $9 "$\r$\n"
FileWrite $9 "$\"intensity$\" : $\"d$\"$\r$\n"
FileWrite $9 "}$\r$\n"
FileClose $9 ; closes the file
SectionEnd
Upvotes: 2
Reputation: 2943
What you're doing wrong is that you're using the handle of the text box directly, so it will not show the actual text but the ID of the handle. To get it to work , edit your poolPageLeavefunction
as below:
Function poolPageLeave
${NSD_GetText} $POOL $POOL
${NSD_GetText} $USER $USER
${NSD_GetText} $PASS $PASS
FunctionEnd
Upvotes: 1