Memento.nsh 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570
  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" "id"
  59. ;
  60. ; ${MementoSectionEx} "[flags]" "name" "memento_id" "section_id"
  61. ;
  62. !define MementoSection "!insertmacro MementoSection"
  63. !define MementoSectionEx "!insertmacro MementoSectionEx"
  64. ;
  65. ; ${MementoSectionEnd}
  66. ;
  67. ; Ends a section previously opened using ${MementoSection}.
  68. ;
  69. ; Usage is similar to SectionEnd.
  70. ;
  71. ; ${MementoSection} "name" "id"
  72. ; # some code...
  73. ; ${MementoSectionEnd}
  74. ;
  75. ;
  76. ; ${MementoUnselectedSection}
  77. ;
  78. ; Defines a section whose state is remembered by Memento and is
  79. ; unselected by default.
  80. ;
  81. ; Usage is similar to Section with the /o switch.
  82. ;
  83. ; ${MementoUnselectedSection} "name" "id"
  84. ;
  85. !define MementoUnselectedSection "!insertmacro MementoUnselectedSection"
  86. ;
  87. ; ${MementoSectionEnd}
  88. ;
  89. ; Ends a section previously opened using ${MementoSection}.
  90. ;
  91. ; Usage is similar to SectionEnd.
  92. ;
  93. ; ${MementoSection} "name" "id"
  94. ; # some code...
  95. ; ${MementoSectionEnd}
  96. ;
  97. !define MementoSectionEnd "!insertmacro MementoSectionEnd"
  98. ;
  99. ; ${MementoSectionDone}
  100. ;
  101. ; Used after all ${MementoSection} have been set.
  102. ;
  103. ; ${MementoSection} "name1" "some_id1"
  104. ; # some code...
  105. ; ${MementoSectionEnd}
  106. ;
  107. ; ${MementoSection} "name2" "some_id2"
  108. ; # some code...
  109. ; ${MementoSectionEnd}
  110. ;
  111. ; ${MementoSection} "name3" "some_id3"
  112. ; # some code...
  113. ; ${MementoSectionEnd}
  114. ;
  115. ; ${MementoSectionDone}
  116. ;
  117. !define MementoSectionDone "!insertmacro MementoSectionDone"
  118. ;
  119. ; ${MementoSectionRestore}
  120. ;
  121. ; Restores the state of all Memento sections from the registry.
  122. ;
  123. ; Commonly used in .onInit.
  124. ;
  125. ; Function .onInit
  126. ;
  127. ; ${MementoSectionRestore}
  128. ;
  129. ; FunctionEnd
  130. ;
  131. !define MementoSectionRestore "!insertmacro MementoSectionRestore"
  132. ;
  133. ; ${MementoSectionSave}
  134. ;
  135. ; Saves the state of all Memento sections to the registry.
  136. ;
  137. ; Commonly used in .onInstSuccess.
  138. ;
  139. ; Function .onInstSuccess
  140. ;
  141. ; ${MementoSectionSave}
  142. ;
  143. ; FunctionEnd
  144. ;
  145. !define MementoSectionSave "!insertmacro MementoSectionSave"
  146. ;
  147. ; MementoSection<ReadWrite><Int|Marker>
  148. ;
  149. ; Replaceable macros that allow custom storage methods to be used.
  150. ;
  151. !define /IfNDef MementoSectionStorageSeparator '_'
  152. !ifmacrondef MementoSectionReadInt
  153. !define __MementoSectionStdRegReadWrite
  154. !define /IfNDef MementoSectionStoragePrefix "MementoSection"
  155. !macro MementoSectionReadInt outvar name
  156. ReadRegDWord ${outvar} ${MEMENTO_REGISTRY_ROOT} `${MEMENTO_REGISTRY_KEY}` `${MementoSectionStoragePrefix}${name}`
  157. !macroend
  158. !macro MementoSectionWriteInt name val
  159. WriteRegDWord ${MEMENTO_REGISTRY_ROOT} `${MEMENTO_REGISTRY_KEY}` `${MementoSectionStoragePrefix}${name}` `${val}`
  160. !macroend
  161. !macro MementoSectionReadMarker outvar name
  162. ReadRegStr ${outvar} ${MEMENTO_REGISTRY_ROOT} `${MEMENTO_REGISTRY_KEY}` `${MementoSectionStoragePrefix}${name}`
  163. !macroend
  164. !macro MementoSectionWriteMarker name
  165. WriteRegStr ${MEMENTO_REGISTRY_ROOT} `${MEMENTO_REGISTRY_KEY}` `${MementoSectionStoragePrefix}${name}` ``
  166. !macroend
  167. !endif
  168. #####################################
  169. ### Internal Defines ###
  170. #####################################
  171. !define __MementoSectionIndex 1
  172. #####################################
  173. ### Internal Macros ###
  174. #####################################
  175. !macro __MementoCheckSettings
  176. !ifdef __MementoSectionStdRegReadWrite
  177. !ifndef MEMENTO_REGISTRY_ROOT | MEMENTO_REGISTRY_KEY
  178. !error "MEMENTO_REGISTRY_ROOT and MEMENTO_REGISTRY_KEY must be defined before using any of Memento's macros"
  179. !endif
  180. !endif
  181. !macroend
  182. !macro __MementoSection flags name mementoid sectionid
  183. !insertmacro __MementoCheckSettings
  184. !ifndef __MementoSectionIndex
  185. !error "MementoSectionDone already used!"
  186. !endif
  187. !define __MementoSectionLastMementoId `${mementoid}`
  188. !define __MementoSectionLastSectionId `${sectionid}`
  189. !define __MementoSectionLastFlags `${flags}`
  190. !verbose pop
  191. Section ${flags} `${name}` `${sectionid}`
  192. !verbose push
  193. !verbose 3
  194. !macroend
  195. #####################################
  196. ### User Macros ###
  197. #####################################
  198. !macro MementoSectionEx flags name mid sid
  199. !verbose push 3
  200. !insertmacro __MementoSection `${flags}` `${name}` `${mid}` `${sid}`
  201. !verbose pop
  202. !macroend
  203. !macro MementoSection name id
  204. !verbose push 3
  205. !insertmacro __MementoSection "" `${name}` `${id}` `${id}`
  206. !verbose pop
  207. !macroend
  208. !macro MementoUnselectedSection name id
  209. !verbose push 3
  210. !insertmacro __MementoSection /o `${name}` `${id}` `${id}`
  211. !verbose pop
  212. !macroend
  213. !macro MementoSectionEnd
  214. SectionEnd
  215. !verbose push
  216. !verbose 3
  217. !insertmacro __MementoCheckSettings
  218. !ifndef __MementoSectionIndex
  219. !error "MementoSectionDone already used!"
  220. !endif
  221. !define /MATH __MementoSectionIndexNext \
  222. ${__MementoSectionIndex} + 1
  223. Function __MementoSectionMarkNew${__MementoSectionIndex}
  224. ClearErrors
  225. !insertmacro MementoSectionReadInt $0 `${MementoSectionStorageSeparator}${__MementoSectionLastMementoId}`
  226. ${If} ${Errors}
  227. !insertmacro SetSectionFlag `${${__MementoSectionLastSectionId}}` ${SF_BOLD}
  228. ${EndIf}
  229. GetFunctionAddress $0 __MementoSectionMarkNew${__MementoSectionIndexNext}
  230. Goto $0
  231. FunctionEnd
  232. Function __MementoSectionRestoreStatus${__MementoSectionIndex}
  233. ClearErrors
  234. !insertmacro MementoSectionReadInt $0 `${MementoSectionStorageSeparator}${__MementoSectionLastMementoId}`
  235. !searchparse /ignorecase /noerrors `${__MementoSectionLastFlags}-` `/o` __MementoSectionUnselected
  236. !ifndef __MementoSectionUnselected
  237. ${If} ${Errors}
  238. ${OrIf} $0 != 0
  239. !insertmacro SelectSection `${${__MementoSectionLastSectionId}}`
  240. ${Else}
  241. !insertmacro UnselectSection `${${__MementoSectionLastSectionId}}`
  242. ${EndIf}
  243. !else
  244. !undef __MementoSectionUnselected
  245. ${If} ${Errors}
  246. ${OrIf} $0 == 0
  247. !insertmacro UnselectSection `${${__MementoSectionLastSectionId}}`
  248. ${Else}
  249. !insertmacro SelectSection `${${__MementoSectionLastSectionId}}`
  250. ${EndIf}
  251. !endif
  252. GetFunctionAddress $0 __MementoSectionRestoreStatus${__MementoSectionIndexNext}
  253. Goto $0
  254. FunctionEnd
  255. Function __MementoSectionSaveStatus${__MementoSectionIndex}
  256. ${If} ${SectionIsSelected} `${${__MementoSectionLastSectionId}}`
  257. !insertmacro MementoSectionWriteInt `${MementoSectionStorageSeparator}${__MementoSectionLastMementoId}` 1
  258. ${Else}
  259. !insertmacro MementoSectionWriteInt `${MementoSectionStorageSeparator}${__MementoSectionLastMementoId}` 0
  260. ${EndIf}
  261. GetFunctionAddress $0 __MementoSectionSaveStatus${__MementoSectionIndexNext}
  262. Goto $0
  263. FunctionEnd
  264. !undef __MementoSectionIndex
  265. !define __MementoSectionIndex ${__MementoSectionIndexNext}
  266. !undef __MementoSectionIndexNext
  267. !undef __MementoSectionLastMementoId
  268. !undef __MementoSectionLastSectionId
  269. !undef __MementoSectionLastFlags
  270. !verbose pop
  271. !macroend
  272. !macro MementoSectionDone
  273. !verbose push
  274. !verbose 3
  275. !insertmacro __MementoCheckSettings
  276. Function __MementoSectionMarkNew${__MementoSectionIndex}
  277. FunctionEnd
  278. Function __MementoSectionRestoreStatus${__MementoSectionIndex}
  279. FunctionEnd
  280. Function __MementoSectionSaveStatus${__MementoSectionIndex}
  281. FunctionEnd
  282. !undef __MementoSectionIndex
  283. !verbose pop
  284. !macroend
  285. !macro MementoSectionRestore
  286. !verbose push
  287. !verbose 3
  288. !insertmacro __MementoCheckSettings
  289. Push $0
  290. Push $1
  291. Push $2
  292. Push $3
  293. # check for first usage
  294. ClearErrors
  295. !insertmacro MementoSectionReadMarker $0 `Used`
  296. ${If} ${Errors}
  297. # use script defaults on first run
  298. Goto done
  299. ${EndIf}
  300. # mark new components in bold
  301. Call __MementoSectionMarkNew1
  302. # mark section groups in bold
  303. StrCpy $0 0
  304. StrCpy $1 ""
  305. StrCpy $2 ""
  306. StrCpy $3 ""
  307. loop:
  308. ClearErrors
  309. ${If} ${SectionIsBold} $0
  310. ${If} $1 != ""
  311. !insertmacro SetSectionFlag $1 ${SF_BOLD}
  312. ${EndIf}
  313. ${If} $2 != ""
  314. !insertmacro SetSectionFlag $2 ${SF_BOLD}
  315. ${EndIf}
  316. ${If} $3 != ""
  317. !insertmacro SetSectionFlag $3 ${SF_BOLD}
  318. ${EndIf}
  319. ${ElseIf} ${Errors}
  320. Goto loop_end
  321. ${EndIf}
  322. ${If} ${SectionIsSectionGroup} $0
  323. ${If} $1 == ""
  324. StrCpy $1 $0
  325. ${ElseIf} $2 == ""
  326. StrCpy $2 $0
  327. ${ElseIf} $3 == ""
  328. StrCpy $3 $0
  329. ${EndIf}
  330. ${EndIf}
  331. ${If} ${SectionIsSectionGroupEnd} $0
  332. ${If} $3 != ""
  333. StrCpy $3 ""
  334. ${ElseIf} $2 != ""
  335. StrCpy $2 ""
  336. ${ElseIf} $1 != ""
  337. StrCpy $1 ""
  338. ${EndIf}
  339. ${EndIf}
  340. IntOp $0 $0 + 1
  341. Goto loop
  342. loop_end:
  343. # restore sections' status
  344. Call __MementoSectionRestoreStatus1
  345. # all done
  346. done:
  347. Pop $3
  348. Pop $2
  349. Pop $1
  350. Pop $0
  351. !verbose pop
  352. !macroend
  353. !macro MementoSectionSave
  354. !verbose push
  355. !verbose 3
  356. !insertmacro __MementoCheckSettings
  357. Push $0
  358. !insertmacro MementoSectionWriteMarker `Used`
  359. Call __MementoSectionSaveStatus1
  360. Pop $0
  361. !verbose pop
  362. !macroend
  363. !endif # ___MEMENTO_NSH___
  364. !verbose pop