2013-06-25 2 views
0

Я строю установщик с NSIS, чтобы помочь мне развернуть cgminer на кучу компьютеров в моем подвале. Программа установки запрашивает две вещи:Переменная внутри строки - возможна ли интерполяция строк в NSIS?

  • майнинг URL и рабочих полномочий
  • каталог, в котором для извлечения cgminer

Установщик использует при условии пользовательский URL пула, имя пользователя и пароль для создания простой конфигурационный файл cgminer.

Вот код, который пишет JSON конфигурационный файл:

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 

Это то, что я ожидал:

{ 
"pools" : [ 
     { 
       "url" : "http://bc.minercity.org:4583", 
       "user" : "fizzlefazzle_miner", 
       "pass" : "rosebud", 
     } 
], 

"intensity" : "d" 
} 

Однако это то, что я получаю:

{ 
"pools" : [ 
     { 
       "url" : "1639776", 
       "user" : "1115594", 
       "pass" : "1115614", 
     } 
], 

"intensity" : "d" 
} 

Я предполагаю, что получаю адреса памяти вместо строк, которые я ввел. Вот код целиком:

; 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 

Что я делаю неправильно?

+1

Я ожидаю, что пользователь и пароль, которые вы опубликовали, являются поддельными. –

+0

Вы используете POOL, USER и PASS для хранения как управляющего адреса, так и пользовательского ввода. Плохая практика. –

+0

Да, пользователь и пропуск являются поддельными. Спасибо Франсиско за то, что он указал на плохую практику. – Grimtech

ответ

2

Нет проблем со строчной интерполяцией. Ваша проблема связана с обработкой текстов редактирования: когда вы указываете, например,

${NSD_CreateText} 0 13u 100% 12u 'http://bc.minercity.org:6347'     
Pop $POOL 
GetFunctionAddress $0 poolChange 
nsDialogs::OnChange $POOL $0 

Вы правильно создаете текст редактирования и сохраняете его дескриптор для использования в определенном обратном вызове. Но позже

FileWrite $9 "$\t$\t$\"url$\" : $\"$POOL$\",$\r$\n" 

Файл записи сохранит дескриптор элемента управления в файле, а не его содержимое.

Также есть некоторые проблемы с обратными вызовами:

  • вы читали различные значения правок в тот же $0 регистра, таким образом $0 будет содержать текст последнего изменения поля только
  • обратных вызовов триггер, когда редактирование изменено, и если пользователь не делает никаких изменений, они не запускаются.

Я бы использовал 3 переменные для дескрипторов редактирования и еще 3 для значений, а затем прочитал значение на обратном вызове страницы. Кроме того, вы можете удалить 3 обратных вызовов, если вы просто хотите, чтобы получить окончательное значение и не хотят реагировать на изменения значения:

!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 
+0

Хорошо, что меня направили в неправильном направлении, пытаясь разыграть указатель, используя системный вызов ... Я неправильно понял регистры, чтобы быть своего рода волшебными интеллектуальными переменными, которые делают то, что я думаю. Это не происходит в программировании, я так наивен! Спасибо за ваше понимание. – Grimtech

+0

@ Grimtech Я только заметил, что вы предложили удалить некоторые нерелевантные строки, которые я забыл удалить относительно обратных вызовов. Редактирование было отклонено сообществом, но вы были правы. Я только что исправил это. – Seki

1

Что вы делаете неправильно, что вы используете ручку текста box, поэтому он не отображает фактический текст, кроме идентификатора дескриптора. Для того, чтобы заставить его работать, редактировать poolPageLeavefunction, как показано ниже:

Function poolPageLeave 
${NSD_GetText} $POOL $POOL 
${NSD_GetText} $USER $USER 
${NSD_GetText} $PASS $PASS 
FunctionEnd 
+0

У меня нет изменений: если он правильно получает контент редактирования сразу после его создания, он тормозит вызов обратного вызова, предоставляя функции значение содержимого редактирования вместо дескриптора элемента управления. И если значение редактируется пользователем, окончательное значение не будет записано в файл конфигурации. – Seki

+0

@ Seki О, да, ты прав. Отредактировал код ... не уверен в нарушении обратного вызова, но отредактированное решение будет работать для него в обоих случаях (если пользователь редактирует или не делает). – foobar

+0

Технически, теперь это нормально в отношении исходного кода OP, странная часть - это просто переменная, которая будет содержать некоторые управляющие ручки в течение некоторого времени и некоторые текстовые значения позже. Я бы не рекомендовал такого рода изменение поведения в любом серьезном коде:^P – Seki