Memento.nsh 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  1. !verbose push
  2. !verbose 3
  3. !include LogicLib.nsh
  4. !include Sections.nsh
  5. !ifndef ___MEMENTO_NSH___
  6. !define ___MEMENTO_NSH___
  7. #####################################
  8. ### Memento ###
  9. #####################################
  10. /*
  11. Memento is a set of macros that allow installers to remember user selection
  12. across separate runs of the installer. Currently, it can remember the state
  13. of sections and mark new sections as bold. In the future, it'll integrate
  14. InstallOptions and maybe even the Modern UI.
  15. A usage example can be found in `Examples\Memento.nsi`.
  16. */
  17. #####################################
  18. ### Usage Instructions ###
  19. #####################################
  20. /*
  21. 1. Declare usage of Memento by including Memento.nsh at the top of the script.
  22. !include Memento.nsh
  23. 2. Define MEMENTO_REGISTRY_ROOT and MEMENTO_REGISTRY_KEY with the a registry key
  24. where sections' state should be saved.
  25. !define MEMENTO_REGISTRY_ROOT HKLM
  26. !define MEMENTO_REGISTRY_KEY \
  27. Software\Microsoft\Windows\CurrentVersion\Uninstall\MyProgram
  28. 3. Replace Section with ${MementoSection} and SectionEnd with ${MementoSectionEnd}
  29. for sections that whose state should be remembered by Memento.
  30. For sections that should be unselected by default, use ${MementoSection}'s
  31. brother - ${MementoUnselectedSection}.
  32. Sections that don't already have an identifier must be assigned one.
  33. Section identifiers must stay the same across different versions of the
  34. installer or their state will be forgotten.
  35. 4. Use ${MementoSectionDone} after the last ${MementoSection}.
  36. 5. Add a call to ${MementoSectionRestore} to .onInit to restore the state
  37. of all sections from the registry.
  38. Function .onInit
  39. ${MementoSectionRestore}
  40. FunctionEnd
  41. 6. Add a call to ${MementoSectionSave} to .onInstSuccess to save the state
  42. of all sections to the registry.
  43. Function .onInstSuccess
  44. ${MementoSectionSave}
  45. FunctionEnd
  46. 7. Tattoo the location of the chosen registry key on your arm.
  47. */
  48. #####################################
  49. ### User API ###
  50. #####################################
  51. ;
  52. ; ${MementoSection}
  53. ;
  54. ; Defines a section whose state is remembered by Memento.
  55. ;
  56. ; Usage is similar to Section.
  57. ;
  58. ; ${MementoSection} "name" "some_id"
  59. ;
  60. !define MementoSection "!insertmacro MementoSection"
  61. ;
  62. ; ${MementoSectionEnd}
  63. ;
  64. ; Ends a section previously opened using ${MementoSection}.
  65. ;
  66. ; Usage is similar to SectionEnd.
  67. ;
  68. ; ${MementoSection} "name" "some_id"
  69. ; # some code...
  70. ; ${MementoSectionEnd}
  71. ;
  72. ;
  73. ; ${MementoUnselectedSection}
  74. ;
  75. ; Defines a section whose state is remembered by Memento and is
  76. ; unselected by default.
  77. ;
  78. ; Usage is similar to Section with the /o switch.
  79. ;
  80. ; ${MementoUnselectedSection} "name" "some_id"
  81. ;
  82. !define MementoUnselectedSection "!insertmacro MementoUnselectedSection"
  83. ;
  84. ; ${MementoSectionEnd}
  85. ;
  86. ; Ends a section previously opened using ${MementoSection}.
  87. ;
  88. ; Usage is similar to SectionEnd.
  89. ;
  90. ; ${MementoSection} "name" "some_id"
  91. ; # some code...
  92. ; ${MementoSectionEnd}
  93. ;
  94. !define MementoSectionEnd "!insertmacro MementoSectionEnd"
  95. ;
  96. ; ${MementoSectionDone}
  97. ;
  98. ; Used after all ${MementoSection} have been set.
  99. ;
  100. ; ${MementoSection} "name1" "some_id1"
  101. ; # some code...
  102. ; ${MementoSectionEnd}
  103. ;
  104. ; ${MementoSection} "name2" "some_id2"
  105. ; # some code...
  106. ; ${MementoSectionEnd}
  107. ;
  108. ; ${MementoSection} "name3" "some_id3"
  109. ; # some code...
  110. ; ${MementoSectionEnd}
  111. ;
  112. ; ${MementoSectionDone}
  113. ;
  114. !define MementoSectionDone "!insertmacro MementoSectionDone"
  115. ;
  116. ; ${MementoSectionRestore}
  117. ;
  118. ; Restores the state of all Memento sections from the registry.
  119. ;
  120. ; Commonly used in .onInit.
  121. ;
  122. ; Function .onInit
  123. ;
  124. ; ${MementoSectionRestore}
  125. ;
  126. ; FunctionEnd
  127. ;
  128. !define MementoSectionRestore "!insertmacro MementoSectionRestore"
  129. ;
  130. ; ${MementoSectionSave}
  131. ;
  132. ; Saves the state of all Memento sections to the registry.
  133. ;
  134. ; Commonly used in .onInstSuccess.
  135. ;
  136. ; Function .onInstSuccess
  137. ;
  138. ; ${MementoSectionSave}
  139. ;
  140. ; FunctionEnd
  141. ;
  142. !define MementoSectionSave "!insertmacro MementoSectionSave"
  143. #####################################
  144. ### Internal Defines ###
  145. #####################################
  146. !define __MementoSectionIndex 1
  147. #####################################
  148. ### Internal Macros ###
  149. #####################################
  150. !macro __MementoCheckSettings
  151. !ifndef MEMENTO_REGISTRY_ROOT | MEMENTO_REGISTRY_KEY
  152. !error "MEMENTO_REGISTRY_ROOT and MEMENTO_REGISTRY_KEY must be defined before using any of Memento's macros"
  153. !endif
  154. !macroend
  155. !macro __MementoSection flags name id
  156. !insertmacro __MementoCheckSettings
  157. !ifndef __MementoSectionIndex
  158. !error "MementoSectionDone already used!"
  159. !endif
  160. !define __MementoSectionLastSectionId `${id}`
  161. !verbose pop
  162. Section ${flags} `${name}` `${id}`
  163. !verbose push
  164. !verbose 3
  165. !macroend
  166. #####################################
  167. ### User Macros ###
  168. #####################################
  169. !macro MementoSection name id
  170. !verbose push
  171. !verbose 3
  172. !insertmacro __MementoSection "" `${name}` `${id}`
  173. !verbose pop
  174. !macroend
  175. !macro MementoUnselectedSection name id
  176. !verbose push
  177. !verbose 3
  178. !insertmacro __MementoSection /o `${name}` `${id}`
  179. !define __MementoSectionUnselected
  180. !verbose pop
  181. !macroend
  182. !macro MementoSectionEnd
  183. SectionEnd
  184. !verbose push
  185. !verbose 3
  186. !insertmacro __MementoCheckSettings
  187. !ifndef __MementoSectionIndex
  188. !error "MementoSectionDone already used!"
  189. !endif
  190. !define /MATH __MementoSectionIndexNext \
  191. ${__MementoSectionIndex} + 1
  192. Function __MementoSectionMarkNew${__MementoSectionIndex}
  193. ClearErrors
  194. ReadRegDWORD $0 ${MEMENTO_REGISTRY_ROOT} `${MEMENTO_REGISTRY_KEY}` `MementoSection_${__MementoSectionLastSectionId}`
  195. ${If} ${Errors}
  196. !insertmacro SetSectionFlag `${${__MementoSectionLastSectionId}}` ${SF_BOLD}
  197. ${EndIf}
  198. GetFunctionAddress $0 __MementoSectionMarkNew${__MementoSectionIndexNext}
  199. Goto $0
  200. FunctionEnd
  201. Function __MementoSectionRestoreStatus${__MementoSectionIndex}
  202. ClearErrors
  203. ReadRegDWORD $0 ${MEMENTO_REGISTRY_ROOT} `${MEMENTO_REGISTRY_KEY}` `MementoSection_${__MementoSectionLastSectionId}`
  204. !ifndef __MementoSectionUnselected
  205. ${If} ${Errors}
  206. ${OrIf} $0 != 0
  207. !insertmacro SelectSection `${${__MementoSectionLastSectionId}}`
  208. ${Else}
  209. !insertmacro UnselectSection `${${__MementoSectionLastSectionId}}`
  210. ${EndIf}
  211. !else
  212. !undef __MementoSectionUnselected
  213. ${If} ${Errors}
  214. ${OrIf} $0 == 0
  215. !insertmacro UnselectSection `${${__MementoSectionLastSectionId}}`
  216. ${Else}
  217. !insertmacro SelectSection `${${__MementoSectionLastSectionId}}`
  218. ${EndIf}
  219. !endif
  220. GetFunctionAddress $0 __MementoSectionRestoreStatus${__MementoSectionIndexNext}
  221. Goto $0
  222. FunctionEnd
  223. Function __MementoSectionSaveStatus${__MementoSectionIndex}
  224. ${If} ${SectionIsSelected} `${${__MementoSectionLastSectionId}}`
  225. WriteRegDWORD ${MEMENTO_REGISTRY_ROOT} `${MEMENTO_REGISTRY_KEY}` `MementoSection_${__MementoSectionLastSectionId}` 1
  226. ${Else}
  227. WriteRegDWORD ${MEMENTO_REGISTRY_ROOT} `${MEMENTO_REGISTRY_KEY}` `MementoSection_${__MementoSectionLastSectionId}` 0
  228. ${EndIf}
  229. GetFunctionAddress $0 __MementoSectionSaveStatus${__MementoSectionIndexNext}
  230. Goto $0
  231. FunctionEnd
  232. !undef __MementoSectionIndex
  233. !define __MementoSectionIndex ${__MementoSectionIndexNext}
  234. !undef __MementoSectionIndexNext
  235. !undef __MementoSectionLastSectionId
  236. !verbose pop
  237. !macroend
  238. !macro MementoSectionDone
  239. !verbose push
  240. !verbose 3
  241. !insertmacro __MementoCheckSettings
  242. Function __MementoSectionMarkNew${__MementoSectionIndex}
  243. FunctionEnd
  244. Function __MementoSectionRestoreStatus${__MementoSectionIndex}
  245. FunctionEnd
  246. Function __MementoSectionSaveStatus${__MementoSectionIndex}
  247. FunctionEnd
  248. !undef __MementoSectionIndex
  249. !verbose pop
  250. !macroend
  251. !macro MementoSectionRestore
  252. !verbose push
  253. !verbose 3
  254. !insertmacro __MementoCheckSettings
  255. Push $0
  256. Push $1
  257. Push $2
  258. Push $3
  259. # check for first usage
  260. ClearErrors
  261. ReadRegStr $0 ${MEMENTO_REGISTRY_ROOT} `${MEMENTO_REGISTRY_KEY}` MementoSectionUsed
  262. ${If} ${Errors}
  263. # use script defaults on first run
  264. Goto done
  265. ${EndIf}
  266. # mark new components in bold
  267. Call __MementoSectionMarkNew1
  268. # mark section groups in bold
  269. StrCpy $0 0
  270. StrCpy $1 ""
  271. StrCpy $2 ""
  272. StrCpy $3 ""
  273. loop:
  274. ClearErrors
  275. ${If} ${SectionIsBold} $0
  276. ${If} $1 != ""
  277. !insertmacro SetSectionFlag $1 ${SF_BOLD}
  278. ${EndIf}
  279. ${If} $2 != ""
  280. !insertmacro SetSectionFlag $2 ${SF_BOLD}
  281. ${EndIf}
  282. ${If} $3 != ""
  283. !insertmacro SetSectionFlag $3 ${SF_BOLD}
  284. ${EndIf}
  285. ${ElseIf} ${Errors}
  286. Goto loop_end
  287. ${EndIf}
  288. ${If} ${SectionIsSectionGroup} $0
  289. ${If} $1 == ""
  290. StrCpy $1 $0
  291. ${ElseIf} $2 == ""
  292. StrCpy $2 $0
  293. ${ElseIf} $3 == ""
  294. StrCpy $3 $0
  295. ${EndIf}
  296. ${EndIf}
  297. ${If} ${SectionIsSectionGroupEnd} $0
  298. ${If} $3 != ""
  299. StrCpy $3 ""
  300. ${ElseIf} $2 != ""
  301. StrCpy $2 ""
  302. ${ElseIf} $1 != ""
  303. StrCpy $1 ""
  304. ${EndIf}
  305. ${EndIf}
  306. IntOp $0 $0 + 1
  307. Goto loop
  308. loop_end:
  309. # restore sections' status
  310. Call __MementoSectionRestoreStatus1
  311. # all done
  312. done:
  313. Pop $3
  314. Pop $2
  315. Pop $1
  316. Pop $0
  317. !verbose pop
  318. !macroend
  319. !macro MementoSectionSave
  320. !verbose push
  321. !verbose 3
  322. !insertmacro __MementoCheckSettings
  323. Push $0
  324. WriteRegStr ${MEMENTO_REGISTRY_ROOT} `${MEMENTO_REGISTRY_KEY}` MementoSectionUsed ""
  325. Call __MementoSectionSaveStatus1
  326. Pop $0
  327. !verbose pop
  328. !macroend
  329. !endif # ___MEMENTO_NSH___
  330. !verbose pop