Показать полную графическую версию : [архив].: NSIS - все вопросы :.
Такая ситуация:
Есть два компонента которые нельзя устанавливать одновременно (как это осуществить с помощью радиобутонов я знаю), но так же нужно сделать так, чтобы оба компонента можно было не устанавливать.
Как я понял, радиобутонами такое сделать можно, если просто добавить "пустой" третий компонент, при выборе которого не будет, соответственно, устанавливаться ни один из первых двух. Считаю такое решение не очень красивым.
Слышал что можно сделать выбор с помощью обычных чекбоксов, на вроде проверки. Если стоит галочка 1, то галочка 2 убирается и наоборот, если стоит галочка 2, то галочка 1 убирается. При этом галочку можно убрать совсем ,и ни один из двух компонентов выбран не будет. Но никак не соображу как такое реализовать.
Подскажите пожалуйста, лучше с примером сразу.
kotkovets
27-01-2011, 12:30
Слышал что можно сделать выбор с помощью обычных чекбоксов, на вроде проверки. »
Можно сделать и так, но нужно делать промежуточное состояние секций.
Т.е выбор нужной секции - двойным нажатием.
!include "MUI2.nsh"
!include "Sections.nsh"
!insertmacro MUI_PAGE_COMPONENTS
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_LANGUAGE "Russian"
OutFile "File.exe"
SectionGroup /e "Компоненты" IDG
Section "Компонент №1" ID_1
SectionEnd
Section /o "Компонент №2" ID_2
SectionEnd
SectionGroupEnd
Function .onInit
StrCpy $1 ${ID_1}
FunctionEnd
Function .onSelChange
!insertmacro StartRadioButtons $1
!insertmacro RadioButton ${ID_1}
!insertmacro RadioButton ${ID_2}
SectionSetFlags ${IDG} ${SECTION_OFF}
!insertmacro EndRadioButtons
FunctionEnd
Всплыла другая проблема.
Если имеются несколько групп секций и в какой-либо функции используется
SectionSetFlags ${IDG} ${SECTION_OFF}
с групп секций (всех) перестают сбрасываться флажки.
Например, если секции в группах относятся к разным InstType и при одном из вариантов должны отключаться все секции в одной из групп, то секции-то отключаются, а вот флажок на самой группе - нет (отключается только если по нему вручную щелкнуть).
Можно ли это как-то исправить?
!include "MUI2.nsh"
!include "Sections.nsh"
!insertmacro MUI_PAGE_COMPONENTS
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_LANGUAGE "Russian"
InstType "все"
InstType "один"
OutFile "File.exe"
Section "Компонент №0" ID_0
SectionIn 1 2
SectionEnd
SectionGroup /e "Компоненты" IDG
Section "Компонент №1" ID_1
SectionIn 1
SectionEnd
Section /o "Компонент №2" ID_2
SectionEnd
SectionGroupEnd
SectionGroup /e "Компоненты 2" IDG2
Section "Компонент №3" ID_3
SectionIn 1
SectionEnd
Section /o "Компонент №4" ID_4
SectionIn 1
SectionEnd
SectionGroupEnd
Function .onInit
StrCpy $1 ${ID_1}
FunctionEnd
Function .onSelChange
!insertmacro StartRadioButtons $1
!insertmacro RadioButton ${ID_1}
!insertmacro RadioButton ${ID_2}
SectionSetFlags ${IDG} ${SECTION_OFF}
!insertmacro EndRadioButtons
FunctionEnd
kotkovets
03-02-2011, 17:45
silione,
Ну здесь, уже не прокатит трюк фиктивного отключения группы - в наличие неопределенные состояния групп, отсюда и глюки.
1. Нужно определить начальное состояние секций и групп.
2. Разработать логику переключения и рулить флагами секций.
И дальше "прыгать" по логическим меткам (Это вечная проблема с секциями в NSIS).
!include "MUI2.nsh"
!include "Sections.nsh"
!insertmacro MUI_PAGE_COMPONENTS
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_LANGUAGE "Russian"
InstType "все"
InstType "один"
OutFile "File.exe"
Section "Компонент №0" ID_0
SectionIn 1 2
SectionEnd
SectionGroup /e "Компоненты" IDG
Section "Компонент №1" ID_1
SectionIn 1
SectionEnd
Section /o "Компонент №2" ID_2
SectionEnd
SectionGroupEnd
SectionGroup /e "Компоненты 2" IDG2
Section "Компонент №3" ID_3
SectionIn 1
SectionEnd
Section /o "Компонент №4" ID_4
SectionIn 1
SectionEnd
SectionGroupEnd
Function .onInit
Push $0
StrCpy $R0 ${ID_1}
SectionGetFlags ${ID_1} $0
IntOp $0 $0 | ${SF_SELECTED}
SectionSetFlags ${ID_1} $0
SectionGetFlags ${ID_2} $0
IntOp $0 $0 & ${SECTION_OFF}
SectionSetFlags ${ID_2} $0
Pop $0
FunctionEnd
Function .onSelChange
Push $0
StrCmp $R0 ${ID_1} Check_ID_1
SectionGetFlags ${ID_1} $0
IntOp $0 $0 & ${SF_SELECTED}
IntCmp $0 ${SF_SELECTED} 0 Done Done
StrCpy $R0 ${ID_1}
SectionGetFlags ${ID_2} $0
IntOp $0 $0 & ${SECTION_OFF}
SectionSetFlags ${ID_2} $0
Goto Done
Check_ID_1:
SectionGetFlags ${ID_2} $0
IntOp $0 $0 & ${SF_SELECTED}
IntCmp $0 ${SF_SELECTED} 0 Done Done
StrCpy $R0 ${ID_2}
SectionGetFlags ${ID_1} $0
IntOp $0 $0 & ${SECTION_OFF}
SectionSetFlags ${ID_1} $0
Done:
Pop $0
FunctionEnd
shell7777
04-02-2011, 17:34
Есть ; one-section.nsi
;
; This example demonstrates how to control section selection.
; It allows only one of the sections of a group to be selected.
;--------------------------------
; Section define/macro header file
; See this header file for more info
!include "Sections.nsh"
;--------------------------------
Name "One Section"
OutFile "one-section.exe"
RequestExecutionLevel user
;--------------------------------
; Pages
Page components
;--------------------------------
; Sections
SectionGroup /e "GROUP" www
Section "Group 1 - Option 1" g1o1
SectionEnd
Section /o "Group 1 - Option 2" g1o2
SectionEnd
Section /o "Group 1 - Option 3" g1o3
SectionEnd
Section "Group 2 - Option 1" g2o1
SectionEnd
Section /o "Group 2 - Option 2" g2o2
SectionEnd
Section /o "Group 2 - Option 3" g2o3
SectionEnd
SectionGroupEnd
;--------------------------------
; Functions
; $1 stores the status of group 1
; $2 stores the status of group 2
Function .onInit
StrCpy $1 ${g1o1} ; Group 1 - Option 1 is selected by default
StrCpy $2 ${g2o1} ; Group 2 - Option 1 is selected by default
FunctionEnd
Function .onSelChange
!insertmacro StartRadioButtons $1
!insertmacro RadioButton ${g1o1}
!insertmacro RadioButton ${g1o2}
!insertmacro RadioButton ${g1o3}
!insertmacro EndRadioButtons
!insertmacro StartRadioButtons $2
!insertmacro RadioButton ${g2o1}
!insertmacro RadioButton ${g2o2}
!insertmacro RadioButton ${g2o3}
!insertmacro EndRadioButtons
FunctionEnd
из инета, который ставить радиобаттон в группе только на одну секцию из этой группы, но при нажатии на общую группу "GROUP"в случайном порядке выставляются галочки, что совсем не нужно. Подскажите плиз как сделать так, чтобы при клике на "GROUP" галочки выставлялись по умолчанию на первые секции в группе?
kotkovets
04-02-2011, 17:40
shell7777,
По этому поводу я уже отвечал здесь (http://forum.oszone.net/post-1566904-917.html)
Function .onInit
SectionSetFlags ${www} ${SECTION_OFF} #отключаем группу
SectionSetFlags ${g1o1} ${SF_SELECTED} #определяем, как отмеченный компонент
SectionSetFlags ${g2o1} ${SF_SELECTED} #определяем, как отмеченный компонент
StrCpy $1 ${g1o1} ; Group 1 - Option 1 is selected by default
StrCpy $2 ${g2o1} ; Group 2 - Option 1 is selected by default
FunctionEnd
shell7777
04-02-2011, 17:47
kotkovets,
огромнейшее приогромнейшее спасибо!!!!
Урааа....
Я, видимо, дуб.
Почему у меня "компонент №3" может отмечаться одновременно с первым или вторым?
И как при всем этом сделать так, чтобы при нажатии на группу "компоненты 1" галочка, либо снималась совсем, либо происходил последовательный перебор между 1, 2 и 3 компонентой?
!include "MUI2.nsh"
!include "Sections.nsh"
!insertmacro MUI_PAGE_COMPONENTS
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_LANGUAGE "Russian"
InstType "все"
InstType "не все"
OutFile "File.exe"
Section "Компонент 0" ID_0
SectionIn 1 2
SectionEnd
SectionGroup /e "Компоненты 1" IDG1
Section /o "Компонент 1" ID_1
SectionIn 2
SectionEnd
Section "Компонент 2" ID_2
SectionIn 1
SectionEnd
Section /o "Компонент 3" ID_3
SectionEnd
SectionGroupEnd
SectionGroup /e "Компоненты 2" IDG2
Section "Компонент 4" ID_4
SectionIn 1
SectionEnd
Section "Компонент 5" ID_5
SectionIn 1
SectionEnd
SectionGroupEnd
Function .onInit
Push $0
StrCpy $R0 ${ID_2}
SectionGetFlags ${ID_1} $0
IntOp $0 $0 & ${SECTION_OFF}
SectionSetFlags ${ID_1} $0
SectionGetFlags ${ID_2} $0
IntOp $0 $0 | ${SF_SELECTED}
SectionSetFlags ${ID_2} $0
SectionGetFlags ${ID_3} $0
IntOp $0 $0 & ${SECTION_OFF}
SectionSetFlags ${ID_3} $0
Pop $0
FunctionEnd
Function .onSelChange
Push $0
StrCmp $R0 ${ID_1} Check_ID_1
SectionGetFlags ${ID_1} $0
IntOp $0 $0 & ${SF_SELECTED}
IntCmp $0 ${SF_SELECTED} 0 Done Done
StrCpy $R0 ${ID_1}
SectionGetFlags ${ID_2} $0
IntOp $0 $0 & ${SECTION_OFF}
SectionSetFlags ${ID_2} $0
SectionGetFlags ${ID_3} $0
IntOp $0 $0 & ${SECTION_OFF}
SectionSetFlags ${ID_3} $0
Goto Done
Check_ID_1:
StrCmp $R0 ${ID_2} Check_ID_2
SectionGetFlags ${ID_2} $0
IntOp $0 $0 & ${SF_SELECTED}
IntCmp $0 ${SF_SELECTED} 0 Done Done
StrCpy $R0 ${ID_2}
SectionGetFlags ${ID_1} $0
IntOp $0 $0 & ${SECTION_OFF}
SectionSetFlags ${ID_1} $0
SectionGetFlags ${ID_3} $0
IntOp $0 $0 & ${SECTION_OFF}
SectionSetFlags ${ID_3} $0
Check_ID_2:
SectionGetFlags ${ID_3} $0
IntOp $0 $0 & ${SF_SELECTED}
IntCmp $0 ${SF_SELECTED} 0 Done Done
StrCpy $R0 ${ID_3}
SectionGetFlags ${ID_1} $0
IntOp $0 $0 & ${SECTION_OFF}
SectionSetFlags ${ID_1} $0
SectionGetFlags ${ID_2} $0
IntOp $0 $0 & ${SECTION_OFF}
SectionSetFlags ${ID_2} $0
Done:
Pop $0
FunctionEnd
kotkovets
06-02-2011, 14:54
silione,
Могу в этом случае (дабы не выносить мозг :) ) порекомендовать так:
http://forum.oszone.net/post-1326443-307.html
Ыыыыыыыыыыыыы... Ну да, это работает, но сейчас задам самый тупой вопрос...
А как при всем этом сделать чтобы только один раз щелкать по строке?
У меня такое ощущение, что замкнутый круг получается, исправляя одну траблу, получаем другую...
kotkovets
07-02-2011, 00:05
А как при всем этом сделать чтобы только один раз щелкать по строке? »
Это вряд ли - ограничение NSIS, ведь когда отмечаешь чебокс группы, должны отмечатся чебоксы или снимается чебоксы в секционной группе, следовательно изменяются флаги секций с 0 на 1. И при отметке чебоксов секций флаги изменяются (с двух сторон палят пушками в секции :), куда им деваться то!). В последнем примере - именно так сделано на такой логике переключения секций, т.е при флаге равным 0 - секция не отмечена и наоборот.
ЗЫ. хотя явно утверждать не буду, что нельзя именно так и сделать переключения...Ведь я всего в NSIS не знаю:)
Где можно почитать про реализацию ключей при "тихой установке" которая используется тут? »
Я, как автор "ключей", готовлю техническую статью о том, как такое сделать, и в частности, как сделать генератор ответов для интсталлятора. Всё будет.
Столкнулся со следующей проблемой:
Для хранения пути к папке, из которой скрипт берёт файлы на упаковку, я использую переменную. Внутри этой переменной я успешно использую другие переменные, объявленные внутри скрипта, но не могу использовать переменные окружения (например, $PROGRAMFILES): компилятор не преобразует их в пути, а воспринимает как простой текст.
Пример участка кода:
!define PRODUCT_NAME "Mega_Project"
!define INSTALL_FILES_PATH "$PROGRAMFILES\${PRODUCT_NAME}"
Section "Install"
File /r "${INSTALL_FILES_PATH}\*.*"
SectionEnd
Реакция компилятора на подобный код:
File: Returning to: "$PROGRAMFILES\Mega_Project"
File: "$PROGRAMFILES\Mega_Project\*.*" -> no files found.
Usage: File [/nonfatal] [/a] ([/r] [/x filespec [...]] filespec [...] |
/oname=outfile one_file_only)
Вопрос: NSIS просто не позволяет делать такие финты или хромает моя реализация?
Спасибо.
kotkovets
17-02-2011, 01:39
хромает ... реализация »
И полное отсутствие чтения справки и просмотров примеров в папке NSIS...
!define - вообще то, эта команда препроцессора NSIS - помещает опр. значение в константу INSTALL_FILES_PATH (в вашем примере). А константа означает - постоянное, неизменное значение. А вы же пытаетесь, предопределенную переменную $PROGRAMFILES засунуть в константу, а на этапе компиляции эта переменная еще не определена !
Читайте справку по NSIS ! и почитайте Справочник по NSIS (http://forum.oszone.net/post-1569008-918.html)
А делать нужно так:
!define INSTALL_FILES_PATH "C:\Program files\Proga"
!define PRODUCT_NAME "Mega_Project"
InstallDir "$PROGRAMFILES\${PRODUCT_NAME}"
Section "Install"
SetOutPath "$INSTDIR"
File /r "${INSTALL_FILES_PATH}\*.*"
SectionEnd
Причем пути для забора файлов в инсталлятор прописываются только абсолютные или относительно компилируемого скрипта или компилятора NSIS
Добрый вечер, только начал изучать NSIS.
Есть проблемка. Во время установки если пользователь выбирает определенную Section скажем установка «Сервера приложений», то перед установкой необходимо дополнительно запросить к примеру порт. То есть как я понимаю перед установкой должно появиться окно с параметром. Как этого добиться?
kotkovets
20-02-2011, 21:05
необходимо дополнительно запросить к примеру порт. То есть как я понимаю перед установкой должно появиться окно с параметром. Как этого добиться? »
Если Вы так хотите сделать, то нужно делать:
1) проверить, отмечена ли нужная секция
2) Если отмечена секция вызывать соответствующий диалог и вызывать при закрытии стр. выбора компонентов.
Самый простой пример, это с использованием плагина DialogsEx (http://winxpregp.narod.ru/mfiles/NSIS/dialogsex.zip)
файлик DialogsEx.dll закидываем в C:\Program Files\NSIS\Plugins
и хедер dialogs.nsh закидываем в C:\Program Files\NSIS\Include
!include "MUI2.nsh"
!include "dialogs.nsh"
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_DIRECTORY
!define MUI_PAGE_CUSTOMFUNCTION_LEAVE COMPONENTSLEAVE ; функция будет выполнена при закрытии стр. компонентов.
!insertmacro MUI_PAGE_COMPONENTS
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_LANGUAGE "Russian"
ShowInstDetails show
InstallDir "$EXEDIR"
OutFile Test.exe
Caption "Test"
Section "Port" SecPort
MessageBox MB_OK "Номер выбраннога порта: $0" ;показываю в качестве примера значение $0
SectionEnd
Function COMPONENTSLEAVE
${If} ${SectionIsSelected} SecPort ;проверка выбрана ли нужная секция
${InputTextBox} "Окно выбора номера порта" "Введите номер порта в поле ввода..." "" "4" "" "" 0
;число 0 - в переменной $0 будет хранится введеное значение порта
;число 4 - соответствует максимально возможному количеству вводимых символов
StrCmp $0 `` 0 +2 ;если в переменной $0 пустое значение возврат на стр. выбора компонентов
Abort
${EndIf}
FunctionEnd
kotkovets спасибо, большое. Предложенный вариант работает, и для меня это выход.
Но возник дополнительный вопрос.
Возможно ли сделать так что после выбора компонентов, и нажатие кнопки "Далее", возникало не отдельное окно с контролом порт, а была бы следующая страница с контролом порт, А после этого уже установка.
BSL, вы можете "нарисовать" свою собственную страницу. Это очень просто. Посмотрите этот пример (http://winreview.ru/NSIS/241/Sozdanie-svoego-installyatora-na-NSIS-Sozdaem-sobstvennie-stranitci-installyatora). Как я понял, вам нужно будет создать только одно текстовое поле и одну надпись.
hb860, и изучал эту ссылку. Загвоздка в том я смогу создать свою страницу, но как научить ее отображать её или нет в зависимости от выбранной секции.
kotkovets
21-02-2011, 12:57
Загвоздка в том я смогу создать свою страницу, но как научить ее отображать её или нет в зависимости от выбранной секции »
Делается точно также, но с небольшой "модификацией". Нечто подобное делал для себя, вот кусок скрипта:
!include "MUI2.nsh"
!include "dialogs.nsh"
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_DIRECTORY
!define MUI_PAGE_CUSTOMFUNCTION_SHOW COMPONENTSSHOW
!insertmacro MUI_PAGE_COMPONENTS
Page custom PortShow PortLeave
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_LANGUAGE "Russian"
ShowInstDetails show
InstallDir "$EXEDIR"
OutFile Test.exe
Caption "Test"
Var Dialog
Var Label
Var Number
Var Port
Section /o "Port" SecPort
MessageBox MB_OK "Номер выбраннога порта: $Port" ;показываю в качестве примера значение $0
SectionEnd
Function COMPONENTSSHOW ;функция при открытии стр. компонентов
${If} ${SectionIsSelected} SecPort ;если выбрана секция
GetDlgItem $0 $HWNDPARENT 1
${NSD_SetText} $0 `$(^NextBtn)` ;переименовываем кнопку
${ElseIfNot} ${SectionIsSelected} SecPort ;если не выбрана секция
GetDlgItem $0 $HWNDPARENT 1
${NSD_SetText} $0 `$(^InstallBtn)` ;переименовываем кнопку
${EndIf}
FunctionEnd
Function .onSelChange
${If} ${SectionIsSelected} SecPort ;если выбрана секция
GetDlgItem $0 $HWNDPARENT 1
${NSD_SetText} $0 `$(^NextBtn)` ;переименовываем кнопку
${ElseIfNot} ${SectionIsSelected} SecPort ;если не выбрана секция
GetDlgItem $0 $HWNDPARENT 1
${NSD_SetText} $0 `$(^InstallBtn)` ;переименовываем кнопку
${EndIf}
FunctionEnd
Function PortShow
${If} ${SectionIsSelected} SecPort ;проверка выбрана ли нужная секция
nsDialogs::Create 1018
Pop $Dialog
${NSD_CreateLabel} 0 0u 130u 13u "Введите в поле ввода номер порта:"
Pop $Label
${NSD_CreateNumber} 0 13u 40% 13u "" ;ввод только цифры
Pop $Number
${NSD_SetTextLimit} $Number 4 ;лимит на 4 символа
nsDialogs::Show
${EndIf}
FunctionEnd
Function PortLeave
${NSD_GetText} $Number $Port ;считываем текст контрола
StrLen $2 $Port ;считываем количество введенных символов с $Port в $2
IntCmp $2 4 +2 0 0 ;если меньше или больше 4 символов - возврат назад
Abort
FunctionEnd
И обязательно все функции, которые работают с секциями, размещать в скрипте после всех секций - для корректного считывания индетификаторов секций.
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.
Available in ZeroNet 1osznRoVratMCN3bFoFpR2pSV5c9z6sTC