네이버 이웃 추가 / GitHub Profile / 카카오톡 채널 추가 / 방명록 / 이용 안내

[NSIS + HM NIS Edit]6. 커스텀 페이지

수성컴 | 2024. 04. 09.
[NSIS + HM NIS Edit]6. 커스텀 페이지

수성컴전자방입니다. 오늘은 NSIS를 이용한 설치기에 개발자 마음대로 UI를 만들어서 커스텀 페이지를 추가해 보겠습니다.

목차

1. NSIS + HM NIS Edit 설치
2. 기본적인 Windows용 설치 프로그램(설치기) 만들기
3. Section과 SectionGroup
4. 환영 이미지, 헤드 이미지, 브랜딩 텍스트, 스플래시 이미지
5. 프로그래밍(변수, 사칙연산, 분기, 조건문, 반복문)

6. 커스텀 페이지(현재 글)
6.1. 인스톨-옵션 파일(*.ini) 만들기
6.2. Label
6.3. Checkbox
6.4. Radio Button
6.5. Text
6.6. Button
6.7. 글 마무리
6.8. 참고 자료

7. 인터넷에서 내려받기

먼저, 기본적인 코드가 필요합니다. 저는 HM NIS Edit의 스크립트 작성 마법사Modern UI를 사용하는 코드를 만들었습니다. 사칙연산 프로그램을 설치하는 설치기를 만들어 볼 것입니다.

6.1. 인스톨-옵션 파일(*.ini) 만들기

인스톨-옵션 파일 만들기
6.1.1. 인스톨-옵션 파일 만들기(왼쪽 위 ‘파일’ 아래 왼쪽에서 3번째)를 클릭합니다.

인스톨-옵션 파일 창
6.1.2. 그러면 이런 창이 뜰 것입니다.

인스톨-옵션 파일 저장 메뉴
6.1.3. 우선 저장하고 시작하겠습니다.

인스톨-옵션 파일 저장 창
6.1.4. 인스톨-옵션 파일의 확장명은 ini입니다.
예제에서는 MyForm.ini로 저장하겠습니다.

디자이너 크기 변경
6.1.5. 빈 곳을 오른쪽 클릭 후 디자이너 크기 변경Modern UI (300/140)을 클릭합니다.

디자이너 창 작아짐
6.1.6. 창이 작아졌습니다.

오른쪽에 메뉴 있음
6.1.7. 오른쪽에는 label, button 등을 선택할 수 있는 단추들과 그것들의 정보를 설정할 수 있는 칸들이 있습니다. 아무것도 선택되지 않았을 때는 이전, 다음, 취소 단추 등을 설정할 수 있습니다.

6.2. Label

Label
label을 클릭하면 Label을 추가할 수 있습니다.
그 아래(화면의 오른쪽) Text 칸의 내용을 수정하여 화면에 출력할 내용을 편집합니다.
···을 클릭하면

텍스트 편집
줄바꿈 등을 포함하여 더 편하게 편집하실 수 있습니다.

6.3. Checkbox

Checkbox는 주로 중복 선택을 허용할 때 사용합니다.

체크박스
FieldNum은 NSIS 코드에서 체크박스 선택 값을 불러올 때 사용하므로 잘 확인해 둡니다. 화면에 출력할 내용은 Text로 작성합니다.
글씨가 자동으로 줄바꿈되며 잘릴 경우 점을 드래그하여 폭을 늘리시면 됩니다.

체크박스 폭 증가
폭이 늘어났습니다.
State는 Checkbox의 선택 여부입니다.(1은 선택됨, 그 외는 선택 해제 상태)

체크박스 정렬
체크박스가 여러 개 있어서 정렬하고자 할 경우 Left, Top, Right, Bottom 값들을 잘 활용하시면 됩니다.

Checkbox Flags
Flags를 활용하여 Checkbox의 옵션들을 설정할 수 있습니다. 예를 들어 Flags를 DISABLED로 설정하면 해당 체크박스는 클릭할 수 없게 됩니다.
Checkbox의 Flags는 GROUP, NOTABSTOP, DISABLED, RIGHT, NOTIFY가 있습니다.

인스톨-옵션 파일(*.ini)을 다 만들었으면 NSIS 코드(*.nsi)를 작성(수정)합니다.

#...
; Welcome page
!insertmacro MUI_PAGE_WELCOME
; License page
!insertmacro MUI_PAGE_LICENSE "license.txt"
; Directory page
!insertmacro MUI_PAGE_DIRECTORY
; Shortcut Page
Page Custom "MyForm"
; Instfiles page
!insertmacro MUI_PAGE_INSTFILES
; Finish page
!define MUI_FINISHPAGE_RUN "$INSTDIR\main.exe"
!insertmacro MUI_PAGE_FINISH

; Uninstaller pages
!insertmacro MUI_UNPAGE_INSTFILES

; Language files
!insertmacro MUI_LANGUAGE "Korean"

; Reserve files
!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS
ReserveFile "MyForm.ini"

Function .oninit
  !insertmacro MUI_INSTALLOPTIONS_EXTRACT "MyForm.ini"
FunctionEnd

Function MyForm
  !insertmacro MUI_INSTALLOPTIONS_DISPLAY_RETURN "MyForm.ini"
FunctionEnd

; MUI end ------

#...

Var ShortcutAllowed
Var URLAllowed

Section "MainSection" SEC01
  SetOutPath "$INSTDIR"
  SetOverwrite on
  File "sub.exe"
  CreateDirectory "$SMPROGRAMS\사칙연산"
  CreateShortCut "$SMPROGRAMS\사칙연산\사칙연산.lnk" "$INSTDIR\main.exe"
  File "mul.exe"
  File "main.exe"
  File "div.exe"
  File "add.exe"

  ReadIniStr $ShortcutAllowed $PLUGINSDIR\MyForm.ini "Field 2" "State"
  ReadIniStr $URLAllowed $PLUGINSDIR\MyForm.ini "Field 3" "State"

  StrCmp $ShortcutAllowed 1 Shortcut Confirm
Shortcut:
  CreateShortCut "$DESKTOP\사칙연산.lnk" "$INSTDIR\main.exe"
Confirm:
  StrCmp $URLAllowed 1 URL fin
URL:
  WriteIniStr "$INSTDIR\${PRODUCT_NAME}.url" "InternetShortcut" "URL" "${PRODUCT_WEB_SITE}"
  CreateShortCut "$SMPROGRAMS\사칙연산\Website.lnk" "$INSTDIR\${PRODUCT_NAME}.url"
fin:
SectionEnd
#...

[Line 9]
Page Custom “MyForm
기본 생성된 코드에서 페이지 목록 중 원하는 위치에 커스텀 페이지를 삽입하는 코드를 작성합니다.
MyForm은 뒤에서 호출할 함수명이 됩니다.

[Line 24]
ReserveFile “MyForm.ini”
직접 만든 인스톨-옵션 파일인 MyForm.ini를 불러오는 코드입니다.

[Line 26~28 .oninit 함수(설치기가 실행될 때 동작할 내용)]
27행) !insertmacro MUI_INSTALLOPTIONS_EXTRACT “MyForm.ini”
MyForm.ini를 추출합니다.

[Line 30~32 MyForm 함수]
31행) !insertmacro MUI_INSTALLOPTIONS_DISPLAY_RETURN “MyForm.ini”
MyForm.ini를 화면에 출력합니다.

[Line 38~39]
Var 변수명
체크박스 개수만큼 전역변수를 선언합니다.

[Line 52]
ReadIniStr $ShortcutAllowed $PLUGINSDIR\MyForm.ini “Field 2” “State”
MyForm.ini에서 FieldNum이 2인 것State 값을 가져와서 ShortcutAllowed 변수에 저장합니다.

[Line 53]
ReadIniStr $URLAllowed $PLUGINSDIR\MyForm.ini “Field 3” “State”
52행과 동일한 원리입니다.

[Line 55]
StrCmp $ShortcutAllowed 1 Shortcut Confirm
$ShortcutAllowed 값이 1이면 Shortcut으로, 1이 아니면 Confirm으로 이동합니다.(Shortcut과 Confirm은 분기를 위한 label 이름)

[Line 56~57]
Shortcut 레이블이 호출되었을 때 실행할 코드입니다.
스크립트 작성 마법사에서 바탕화면 바로가기 생성 옵션을 체크한 경우 해당 코드를 여기로 옮기시면 됩니다.

[Line 58~59]
Confirm 레이블이 호출되었을 때 실행할 코드입니다.
59행) StrCmp $URLAllowed 1 URL fin
$URLAllowed 값이 1이면 URL로, 1이 아니면 fin으로 이동합니다.

[Line 60~61]
URL 레이블이 호출되었을 때 실행할 코드입니다.
스크립트 작성 마법사에서 웹사이트 바로가기 생성 옵션을 체크한 경우 해당 코드를 여기로 옮기시면 됩니다.

[Line 63~64]
fin 레이블은 SectionEnd 직전에 놓습니다.

체크박스 결과 초기
컴파일 및 실행해 보면 체크박스를 선택할 수 있게 창이 뜹니다.

체크박스 결과 선택
‘바탕화면에 바로가기 추가’만 체크해 보겠습니다.

바로가기 생성됨
코딩한 대로 바탕화면에 바로가기가 생성되었습니다.

6.4. Radio Button

라디오 버튼
이번에는 Radio.ini를 따로 만들겠습니다. 라디오 버튼을 2개 넣어서 ‘예’와 ‘아니요’ 중에서 선택하게 했습니다.

라디오 버튼 아니요를 기본으로
창이 떴을 때 ‘아니요’가 기본적으로 선택되어 있도록 ‘아니요(설치하지 않기)’의 State를 1로 설정했습니다.

라디오 버튼의 Flags는 GROUP, NOTABSTOP, DISABLED, RIGHT, NOTIFY가 있습니다.

#...
; Welcome page
!insertmacro MUI_PAGE_WELCOME
; Intro Page
Page Custom "Radio" #커스텀 페이지 추가
; License page
!insertmacro MUI_PAGE_LICENSE "license.txt"
; Directory page
!insertmacro MUI_PAGE_DIRECTORY
#...
; Instfiles page
!insertmacro MUI_PAGE_INSTFILES
; Finish page
!define MUI_FINISHPAGE_RUN "$INSTDIR\main.exe"
!insertmacro MUI_PAGE_FINISH

; Uninstaller pages
!insertmacro MUI_UNPAGE_INSTFILES

; Language files
!insertmacro MUI_LANGUAGE "Korean"

; Reserve files
!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS
ReserveFile "Radio.ini"
#...

Function .oninit
  !insertmacro MUI_INSTALLOPTIONS_EXTRACT "Radio.ini" #Radio.ini를 추출합니다.
  #...
FunctionEnd

Function Radio
  !insertmacro MUI_INSTALLOPTIONS_DISPLAY_RETURN "Radio.ini"  #Radio.ini를 화면에 출력합니다.
FunctionEnd

#...

; MUI end ------

#...

Var InstallY

Section "MainSection" SEC01
  ReadIniStr $InstallY $PLUGINSDIR\Radio.ini "Field 2" "State"
  StrCmp $InstallY 1 Install Exit

Exit:
  MessageBox MB_OK "프로그램을 설치하지 않고 종료합니다."
  goto fin

Install:
  #...(파일들을 설치하는 코드)
SectionEnd
#...

이전 문단의 Checkbox 관련 코드는 #...으로 생략하겠습니다. 커스텀 페이지에 공통적으로 적용되는 설명 또한 앞에서 진행했으므로 앞으로 생략하겠습니다.

[Line 43]
Var InstallY
라디오 버튼 개수만큼 전역변수를 선언합니다. 다만, 저는 라디오 버튼이 2개이고 예/아니요 방식이라서 변수 1개로 구현하겠습니다.

[Line 46]
ReadIniStr $InstallY $PLUGINSDIR\Radio.ini “Field 2” “State”
Radio.ini에서 FieldNum이 2인 것State 값을 가져와서 InstallY 변수에 저장합니다.

[Line 47]
StrCmp $InstallY 1 Install Exit
$InstallY 값이 1이면 Install로, 1이 아니면 Exit으로 이동합니다.

[Line 49~51]
Exit 레이블이 호출되었을 때 실행할 코드입니다.
파일들을 설치하지 않고 fin 레이블로 이동하게 했습니다.

[Line 53~54]
Install 레이블이 호출되었을 때 실행할 코드입니다.
스크립트 작성 마법사로 생성한 코드들을 잘 편집하여 구성합니다.

[Line 56]
fin 레이블은 SectionEnd 직전에 놓습니다.

라디오 버튼 결과
컴파일 및 실행해 보면 라디오 버튼이 나타나고, ‘아니요’를 선택하면 설치되지 않습니다.

6.5. Text

설치기에서 사용자에게 값을 입력받아 설치하는 방법을 알아보겠습니다. 예제에서는 바로가기 아이콘의 이름을 입력받겠습니다. Text.ini를 만들겠습니다.

텍스트 상자 사칙연산 프로그램
Text의 경우 State에 기본값을 입력해 둘 수 있습니다. 저는 ‘사칙연산 프로그램’으로 설정해 두겠습니다.

Text의 Flags는 GROUP, NOTABSTOP, DISABLED, ONLY_NUMBERS, MULTILINE, VSCROLL, HSCROLL, WANTRETURN, READONLY, NOWORDWRAP이 있습니다.

#...
; Welcome page
!insertmacro MUI_PAGE_WELCOME
#...
; License page
!insertmacro MUI_PAGE_LICENSE "license.txt"
; Directory page
!insertmacro MUI_PAGE_DIRECTORY
#...
; Blog Name Page
Page Custom "Text"  #커스텀 페이지 추가
; Instfiles page
!insertmacro MUI_PAGE_INSTFILES
; Finish page
!define MUI_FINISHPAGE_RUN "$INSTDIR\main.exe"
!insertmacro MUI_PAGE_FINISH

; Uninstaller pages
!insertmacro MUI_UNPAGE_INSTFILES

; Language files
!insertmacro MUI_LANGUAGE "Korean"

; Reserve files
!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS
#...
ReserveFile "Text.ini"  #Text.ini를 추출합니다.

Function .oninit
  #...
  !insertmacro MUI_INSTALLOPTIONS_EXTRACT "Text.ini"  #Text.ini를 화면에 출력합니다.
FunctionEnd

#...

Function Text
  !insertmacro MUI_INSTALLOPTIONS_DISPLAY_RETURN "Text.ini"
FunctionEnd

; MUI end ------

Name "${PRODUCT_NAME} ${PRODUCT_VERSION}"
OutFile "Setup.exe"
InstallDir "$PROGRAMFILES64\사칙연산"
InstallDirRegKey HKLM "${PRODUCT_DIR_REGKEY}" ""
ShowInstDetails show
ShowUnInstDetails show

#...
Var ShortcutName

Section "MainSection" SEC01
  #...

Install:
  SetOutPath "$INSTDIR"
  SetOverwrite on
  File "sub.exe"
  CreateDirectory "$SMPROGRAMS\사칙연산"
  CreateShortCut "$SMPROGRAMS\사칙연산\사칙연산.lnk" "$INSTDIR\main.exe"
  File "mul.exe"
  File "main.exe"
  File "div.exe"
  File "add.exe"

  #...
  ReadIniStr $ShortcutName $PLUGINSDIR\Text.ini "Field 2" "State"
  #...
  CreateShortCut "$DESKTOP\$ShortcutName.lnk" "$INSTDIR\main.exe"
  #...
SectionEnd
#...

[Line 50]
Var ShortcutName
텍스트 상자 개수만큼 전역변수를 선언합니다.

[Line 67]
ReadIniStr $ShortcutName $PLUGINSDIR\Text.ini “Field 2” “State”
Text.ini에서 FieldNum이 2인 것State 값을 가져와서 ShortcutName 변수에 저장합니다.

[Line 69]
CreateShortCut “$DESKTOP\$ShortcutName.lnk” “$INSTDIR\main.exe”
스크립트 작성 마법사에서 바탕화면 바로가기 생성 옵션을 체크한 경우 해당 코드를 여기로 옮기시면 됩니다. 다만, 이때 바탕화면 바로가기의 이름을 $ShortcutName으로 합니다.

설치기에서 바로가기 이름 설정
컴파일 및 실행해 보면 설치기 창에서 바로가기 이름 설정하는 화면을 보실 수 있습니다.
기본적으로 위에서 설정한 State 값이 입력되어 있지만 변경할 수도 있습니다.

바로가기 생성 결과
설정한 이름으로 바탕화면 바로가기가 생성되었습니다.

6.6. Button

제 생각에는 오늘 다루는 내용 중에서 Button이 가장 어려운 것 같습니다.
Button.ini를 만들어 보겠습니다.

버튼 만들기
버튼을 2개 만들어서 클릭한 것에 따라 다른 결과로 이어지게 해 보겠습니다.
버튼을 클릭하면 바로 다음 화면으로 넘어가게 하기 위해서 각 버튼의 Flags를 NOTIFY로 설정해야 합니다.

참고로 Button의 Flags는 Group, NOTABSTOP, DISABLED, NOTIFY가 있습니다.

#...
; Welcome page
!insertmacro MUI_PAGE_WELCOME
; Intro Page
#...
Page Custom "Button" "ButtonLeave"
; License page
!insertmacro MUI_PAGE_LICENSE "license.txt"
; Directory page
!insertmacro MUI_PAGE_DIRECTORY
#...
; Instfiles page
!insertmacro MUI_PAGE_INSTFILES
; Finish page
!define MUI_FINISHPAGE_RUN "$INSTDIR\main.exe"
!insertmacro MUI_PAGE_FINISH

; Uninstaller pages
!insertmacro MUI_UNPAGE_INSTFILES

; Language files
!insertmacro MUI_LANGUAGE "Korean"

; Reserve files
!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS
ReserveFile "Button.ini"
#...

Function .oninit
  !insertmacro MUI_INSTALLOPTIONS_EXTRACT "Button.ini"  #Button.ini를 추출합니다.
  #...
FunctionEnd

Var ButtonClick
Function Button
  !insertmacro MUI_INSTALLOPTIONS_DISPLAY_RETURN "Button.ini" #Button.ini를 화면에 출력합니다.
FunctionEnd
Function ButtonLeave
  !insertmacro MUI_INSTALLOPTIONS_READ $ButtonClick "Button.ini" "Settings" "State"
FunctionEnd

#...

; MUI end ------

Name "${PRODUCT_NAME} ${PRODUCT_VERSION}"
OutFile "Setup.exe"
InstallDir "$PROGRAMFILES64\사칙연산"
InstallDirRegKey HKLM "${PRODUCT_DIR_REGKEY}" ""
ShowInstDetails show
ShowUnInstDetails show

#...

Section "MainSection" SEC01
  #...

  StrCmp $ButtonClick 2 Install +1
  StrCmp $ButtonClick 3 OnlyLink +1

Install:
  SetOutPath "$INSTDIR"
  SetOverwrite on
  File "sub.exe"
  #...(그 외 프로그램 파일 설치 코드)

OnlyLink:
  #...
  CreateShortCut "$DESKTOP\$ShortcutName.lnk" "$INSTDIR\main.exe"
  #...(그 외 바로가기 설치 코드)
SectionEnd
#...

[Line 6]
Page Custom “Button” “ButtonLeave”
기본 생성된 코드에서 페이지 목록 중 원하는 위치에 커스텀 페이지를 삽입하는 코드를 작성합니다.
Button은 이번 커스텀 페이지를 띄우기 위한 함수입니다. 커스텀 페이지를 띄우기 전에 처리됩니다.
ButtonLeave는 이번 커스텀 페이지를 나갈 때(ex. 버튼 클릭) 작동할 함수입니다.

[Line 34]
Var ButtonClick
전역변수를 선언합니다. 버튼 개수와 상관없이 1개만 사용할 것입니다.

[Line 35~37 “Button” 함수]
36행) !insertmacro MUI_INSTALLOPTIONS_DISPLAY_RETURN “Button.ini”
Button.ini를 화면에 출력합니다.

[Line 38~40 “ButtonLeave” 함수]
39행) !insertmacro MUI_INSTALLOPTIONS_READ $ButtonClickButton.ini” “Settings” “State”
Button.ini의 버튼 클릭한 것의 FieldNum을 ButtonClick에 저장합니다. 39행 코드에는 특정 FieldNum이 아니라 “Settings”라고 적는다는 점을 유의하시기 바랍니다.

[Line 58]
StrCmp $ButtonClick 2 Install +1
$ButtonClick이 2이면 FieldNum이 2인 버튼을 클릭했다는 뜻입니다. 제가 만든 Button.ini에서 FieldNum이 2인 버튼은 ‘프로그램 설치’이므로 Install로 이동하게 했습니다. $ButtonClick이 2가 아니면 아랫줄(+1)로 이동합니다.

[Line 59]
StrCmp $ButtonClick 3 OnlyLink +1
$ButtonClick이 3이면 FieldNum이 3인 버튼을 클릭했다는 뜻입니다. 제가 만든 Button.ini에서 FieldNum이 3인 버튼은 ‘프로그램 바로가기만 생성’이므로 OlnyLink로 이동하게 했습니다. $ButtonClick이 3이 아니면 아랫줄(+1)로 이동합니다.

[Line 61~65]
Install 레이블이 호출되었을 때 실행할 코드입니다.
스크립트 작성 마법사로 생성한 코드들을 잘 편집하여 구성합니다.

[Line 67~71]
OnlyLink 레이블이 호출되었을 때 실행할 코드입니다.
스크립트 작성 마법사로 생성한 코드들을 잘 편집하여 구성합니다.

버튼 결과
컴파일 및 실행해 보면 버튼들을 보실 수 있습니다.

6.7. 글 마무리

오늘은 여기까지! 제 글을 읽어 주셔서 감사합니다.
다음에 만나요~!

6.8. 참고 자료

1) 애스크. 2019. “[NSIS+HM NIS EDIT]5강 - 커스텀페이지”, YouTube. (2024. 04. 09. 방문). https://youtu.be/gdao3FrtVrA?si=eBYQimLzfbX2Uayy
2) Fogria. 2012. “커스텀 페이지 연결법”, 포그리아의 무한창고. (2024. 04. 09. 방문). https://fogria2.tistory.com/entry/커스텀-페이지-연결법
3) Afrow UK. 2010. “Adding custom installer pages”, NSIS Wiki. (2024. 04. 09. 방문). https://nsis.sourceforge.io/Adding_custom_installer_pages