NSIS (Nullsoft Scriptable Install System): Add Second License and Installation Page


Jadi, ceritanya sekitar 2 minggu yang lalu saya mendapatkan tugas baru lagi yang masih berkaitan dengan NSIS. Tulisan sebelumnya mengenai NSIS dapat dilihat di sini. Tugas kali ini ialah mengikutsertakan aplikasi NTP Server and Time Monitor  (selanjutnya saya sebut sebagai NTPS saja) ke dalam installer yang telah ada sebelumnya. Menambahkan 3rd-party apps sebenarnya merupakan hal yang mudah (cukup bertanya ke paman Google). Masalahnya ada di spesifikasi sang manajer: sebelum proses instalasi dimulai, user harus melihat license page baru terkait NTPS dan apabila user setuju, NTPS akan di-install sedangkan bila user tidak setuju, halaman instalasi akan langsung berpindah ke finish page.

Perlu diketahui, tipe instalasi ada dua macam, Silent Install dan Non-Silent Install. Untuk kasus ini, instalasi NTPS harus silent install dan license page yang ditampilkan bukanlah license page langsung dari NTPS, melainkan sebuah page baru yang akan menampilkan GNU General Public License (GNU GPL). Sewaktu saya diberi tugas pertama, semua contoh yang saya lihat hanya menggunakan satu license page dan satu install page. Saya pun bertanya-tanya apakah mungkin menggunakan lebih dari satu license dan install page. Jika tidak bisa, maka satu-satunya jalan adalah membuat custom page (caranya hampir serupa dengan membuat custom page untuk mengecek spesifikasi hardware).

Karena tidak menemukan apa yang saya cari di Google, saya pun melontarkan pertanyaan di sini. Ada satu jawaban yang mengatakan bahwa di dalam sebuah installer hanya dapat menggunakan satu page untuk setiap jenis page yang ada di NSIS MUI (Modern User Interface). Saat membaca komentar tersebut, saya pun akhirnya pasrah dan mulai membuat page custom. Tapi, tak lama kemudian, ada jawaban lain yang mengatakan boleh menggunakan multiple page dan itu pun disertai dengan contoh😀

Saya pun mencoba contoh tersebut (tentunya dengan berbagai modifikasi untuk menyesuaikan dengan spesifikasi yang diberikan) dan ternyata hasilnya tidak seperti yang saya harapkan. Karena tidak berhasil, saya mencoba melanjutkan pembuatan page custom yang tadinya sudah ditelantarkan. Ternyata hasilnya juga tidak sesuai dengan harapan saya. Saya kembali bertanya pada paman Google dan hasilnya nihil. Jadi, tampaknya kasus saya ini cukup langka (atau mungkin sudah ada yang pernah membuatnya tapi tidak dipublikasikan). Oh iya, hal yang paling menyebalkan di dalam pengerjaan installer script ini adalah saya tidak bisa mencobanya begitu saja. Installer script harus di-compile terlebih dahulu sehingga menghasilkan installer barulah saya bisa mencobanya. Compile-nya pun cukup memakan waktu😐

I. Menggunakan custom page:

page custom ShowSecondLicense

Var Lic2Dialog
Var RichTextLicense
Var LabelTextBottom
Var CheckBoxAgree

Function ShowSecondLicense
     StrCpy $R8 2
     StrCpy $R7 0

     !insertmacro MUI_HEADER_TEXT "License Agreement for NTP Server and Time Monitor" "Please review the license terms before installing NTP Server and Time Monitor"

     ; === disable Back button
     GetDlgItem $0 $HWNDPARENT 3
     EnableWindow $0 0

     ; === disable Cancel button
     GetDlgItem $0 $HWNDPARENT 2
     EnableWindow $0 0

     ; === change Next button text to "Skip"
     GetDlgItem $0 $HWNDPARENT 1
     SendMessage $0 ${WM_SETTEXT} 0 "STR:Skip"

     nsDialogs::Create 1018
     Pop $Lic2Dialog

     ; === RichText1 (type: RichText) ===
     nsDialogs::CreateControl RichEdit20A ${ES_READONLY}|${WS_VISIBLE}|${WS_CHILD}|${WS_TABSTOP}|${WS_VSCROLL}|${ES_MULTILINE}|${ES_WANTRETURN} ${WS_EX_STATICEDGE} 17.77u 7.38u 261.32u 80u ""
     Pop $RichTextLicense
     File "/oname=$pluginsdir\GPL.txt" "${SOURCEFOLDER}\GPL.txt"
     nsRichEdit::Load $RichTextLicense "$pluginsdir\GPL.txt"

     ${NSD_CreateCheckBox} 17.77u 117.54u 248.81u 14.77u "I accept the license terms"
     Pop $CheckBoxAgree
     ${NSD_OnClick} $CheckBoxAgree CustomLicense_CheckBoxAgree_Click

     ; === LabelTextBottom (type: Label) ===
     ${NSD_CreateLabel} 17.77u 96u 256.05u 19.69u "You must accept the agreement to continue the NTP Server    and Time Monitor installation."
     Pop $LabelTextBottom

     !insertmacro SelectSection ${SEC0013}
     !insertmacro UnselectSection ${SEC0000}
     !insertmacro UnselectSection ${SEC0002}
     !insertmacro UnselectSection ${SEC0003}
     !insertmacro UnselectSection ${SEC0004}
     !insertmacro UnselectSection ${SEC0005}
     !insertmacro UnselectSection ${SEC0007}
     !insertmacro UnselectSection ${SEC0010}
     !insertmacro UnselectSection ${SEC0011}
     !insertmacro UnselectSection ${SEC0012}

     nsDialogs::Show
FunctionEnd

Function CustomLicense_CheckBoxAgree_Click
     ${NSD_GetState} $CheckBoxAgree $R0
     ${If} $R0 == ${BST_CHECKED}
           StrCpy $R7 1
           GetDlgItem $R0 $HWNDPARENT 1
           SendMessage $R0 ${WM_SETTEXT} 0 "STR:Install"
           EnableWindow $R0 1
     ${Else}
           StrCpy $R7 0
           GetDlgItem $R0 $HWNDPARENT 1
           SendMessage $R0 ${WM_SETTEXT} 0 "STR:Skip"
           EnableWindow $R0 1
     ${EndIf}
FunctionEnd

Function Inst2Pre
     StrCmp $R7 0 0 ContinueInstall
     StrCmp $R8 2 0 End
     SetAutoClose true
          Abort
     End:
     ContinueInstall:
FunctionEnd

Berikut ini penjelasannya:

  • File "/oname=$pluginsdir\GPL.txt" "${SOURCEFOLDER}\GPL.txt": Sebelumnya saya langsung menggunakan nsRichEdit::Load $RichTextLicense "${SOURCEFOLDER}\GPL.txt" dan file-nya tidak terbaca. Ternyata ${SOURCEFOLDER} itu untuk compile time sehingga file-nya harus dipindahkan ke suatu tempat pada saat proses instalasi.
  • SelectSection dan UnselectSection berguna untuk memilih bagian mana saja yang akan di-install. Karena proses instalasi dibagi dua, tentu saja bagian yang sudah di-install di tahap pertama tidak perlu lagi di-install di tahap kedua.
  • CustomLicense_CheckBoxAgree_Click: jika user setuju dengan license-nya, maka tulisan di tombol “Next” akan berubah menjadi “Install”, jika tidak, tulisannya akan berubah menjadi “Skip”
  • Inst2Pre: merupakan callback function yang akan dipanggil sebelum MUI_PAGE_INSTFILES ditampilkan. SetAutoClose true diperlukan agar halaman instalasi tidak muncul. Jika tidak di-set true, maka halaman instalasi akan tetap tampil dengan tulisan complete installation dan user masih harus menekan tombol Next untuk berpindah ke Finish page.

II. Menggunakan license page dari MUI2:

!define MUI_CUSTOMFUNCTION_ABORT onUserAbort

; === installer pages
!insertmacro MUI_PAGE_WELCOME
page custom CheckHWSpecs ShowNotMeetRequirementDialog
!insertmacro MUI_PAGE_LICENSE "${SOURCEFOLDER}\CDA_update061702.txt"
!define MUI_DIRECTORYPAGE_VERIFYONLEAVE
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_STARTMENU Application $StartMenuGroup
!insertmacro MUI_PAGE_INSTFILES
!define MUI_PAGE_HEADER_TEXT "License Agreement for NTP Server and Time Monitor"
!define MUI_PAGE_HEADER_SUBTEXT "Please review the license terms before installing NTP Server and Time Monitor"
!define MUI_LICENSEPAGE_TEXT_BOTTOM "If you accept the terms of the agreement, click the checkbox below. You must accept the agreement to install NTP Server and Time Monitor. Click Install to start the installation."
!define MUI_LICENSEPAGE_CHECKBOX
!define MUI_LICENSEPAGE_CHECKBOX_TEXT "I have read and agree to the license agreement terms"
!define MUI_PAGE_CUSTOMFUNCTION_SHOW Lic2Show
!define MUI_PAGE_CUSTOMFUNCTION_LEAVE Lic2Leave
!insertmacro MUI_PAGE_LICENSE "${SOURCEFOLDER}\GPL.txt"
!define MUI_PAGE_CUSTOMFUNCTION_PRE Inst2Pre
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES

var installBonus

Function Lic2Show
     StrCpy $installBonus 1
     GetDlgItem $0 $hwndparent 2
     SendMessage $0 ${WM_SETTEXT} 0 "STR:&Skip"
     !insertmacro UnselectSection ${SEC0000}
     !insertmacro UnselectSection ${SEC0002}
     !insertmacro UnselectSection ${SEC0003}
     !insertmacro UnselectSection ${SEC0004}
     !insertmacro UnselectSection ${SEC0005}
     !insertmacro UnselectSection ${SEC0007}
     !insertmacro UnselectSection ${SEC0010}
     !insertmacro UnselectSection ${SEC0011}
     !insertmacro UnselectSection ${SEC0012} ; Already installed, uncheck
FunctionEnd

Function Lic2Leave
     ${If} $installBonus == 1
          !insertmacro SelectSection ${SEC0013}
     ${EndIf}
FunctionEnd

Function onUserAbort
     ${If} $installBonus == 1
          StrCpy $installBonus 0
          System::Call 'USER32::PostMessage(i$HWNDPARENT,i0x408,i 1,i0)' ; Delayed skip 1 page
          Abort
     ${EndIf}
FunctionEnd

Function Inst2Pre
     ${If} $installBonus == 0
          SetAutoClose true
          Abort
     ${EndIf}
FunctionEnd

Saya sendiri akhirnya tidak jadi menggunakan custom page yang sudah saya buat sebelumnya karena saya lebih suka dengan tampilan MUI2 yang sudah diatur sedemikian rupa. Berikut ini penjelasan dari menggunakan license page MUI2:

  • !define MUI_CUSTOMFUNCTION_ABORT onUserAbort: fungsi onUserAbort akan dipanggil ketika user menekan tombol apapun yang menyebabkan instalasi gagal (dalam kasus ini: tombol Cancel). Perhatikan saja ketika user menekan tombol Cancel di sebuah installer, biasanya installer tersebut akan langsung tertutup tanpa ada pemberitahuan apa-apa.
  • Lic2Show dan Lic2Leave merupakan callback function untuk license page. Di dalam fungsi Lic2Show, bagian-bagian yang telah di-install sebelumnya tidak akan dipilih lagi dan variabel installBonus diisi dengan nilai 1. Kemudian di dalam fungsi Lic2Leave akan dilakukan pengecekan terhadap variabel installBonus. Jika nilainya == 1, maka bagian NTPS akan dipilih untuk di-install.
  • onUserAbort: pada fungsi ini juga dilakukan pengecekan terhadap variabel installBonus. Jika bernilai 1, berarti user saat ini sedang berada di license page kedua. System::Call 'USER32::PostMessage(i$HWNDPARENT,i0x408,i 1,i0)' berfungsi untuk memberikan delay 1 detik sehingga installer tidak langsung tertutup ketika user menekan tombol cancel dan beralih ke finish page. Apabila fungsi tersebut tidak ada, maka ketika user menekan tombol cancel, installer akan langsung tertutup.
  • Inst2Pre merupakan callback function untuk MUI_PAGE_INSTFILES yang kedua. Di sini dilakukan pengecekan juga terhadap installBonus. Jika nilainya == 0, halaman ini akan di-skip dan langsung berpindah ke finish page. Jika 1, maka halaman ini akan tetap ditampilkan dan sesi instalasi NTPS dimulai.

Semoga bermanfaat.

再見!

signatureblack

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s