NsisComposer.ts 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. import { relative, resolve, win32 } from 'path';
  2. import { readdir, lstat } from 'fs-extra';
  3. import { fixWindowsVersion } from '../util';
  4. export interface INsisComposerOptions {
  5. // Basic.
  6. appName: string;
  7. companyName: string;
  8. description: string;
  9. version: string;
  10. copyright: string;
  11. icon: string;
  12. unIcon: string;
  13. // Compression.
  14. compression: 'zlib' | 'bzip2' | 'lzma';
  15. solid: boolean;
  16. languages: string[];
  17. installDirectory: string;
  18. // Output.
  19. output: string;
  20. }
  21. export class NsisComposer {
  22. public static DIVIDER = '################################################################################';
  23. protected fixedVersion: string;
  24. constructor(protected options: INsisComposerOptions) {
  25. if(!this.options.appName) {
  26. this.options.appName = 'NO_APPNAME';
  27. }
  28. if(!this.options.companyName) {
  29. this.options.companyName = 'NO_COMPANYNAME';
  30. }
  31. if(!this.options.description) {
  32. this.options.description = 'NO_DESCRIPTION';
  33. }
  34. if(!this.options.version) {
  35. this.options.version = 'NO_VERSION';
  36. }
  37. if(!this.options.copyright) {
  38. this.options.copyright = 'NO_COPYRIGHT';
  39. }
  40. this.options.compression = this.options.compression || 'lzma';
  41. this.options.solid = this.options.solid ? true : false;
  42. this.options.languages = this.options.languages && this.options.languages.length > 0 ? this.options.languages : [ 'English' ];
  43. this.fixedVersion = fixWindowsVersion(this.options.version);
  44. }
  45. public async make(): Promise<string> {
  46. return `${ NsisComposer.DIVIDER }
  47. #
  48. # Generated by nsis-gen.
  49. #
  50. ${ NsisComposer.DIVIDER }
  51. ${ await this.makeStrings() }
  52. ${ await this.makeGeneral() }
  53. ${ await this.makeModernUI() }
  54. ${ await this.makeVersioning() }
  55. ${ await this.makeHooks() }
  56. ${ await this.makeInstallSection() }
  57. ${ await this.makeUninstallSection() }`;
  58. }
  59. protected async makeStrings(): Promise<string> {
  60. return `${ NsisComposer.DIVIDER }
  61. #
  62. # Strings
  63. #
  64. ${ NsisComposer.DIVIDER }
  65. !define _APPNAME "${ this.options.appName }"
  66. !define _COMPANYNAME "${ this.options.companyName }"
  67. !define _DESCRIPTION "${ this.options.description }"
  68. !define _VERSION "${ this.fixedVersion }"
  69. !define _COPYRIGHT "${ this.options.copyright }"
  70. !define _OUTPUT "${ win32.normalize(resolve(this.options.output)) }"
  71. # FIXME: More translations.
  72. LangString CREATE_DESKTOP_SHORTCUT 1033 "Create Desktop Shortcut"
  73. LangString CREATE_DESKTOP_SHORTCUT 2052 "创建桌面快捷方式"
  74. LangString CREATE_DESKTOP_SHORTCUT 1028 "建立桌面捷徑"
  75. LangString INSTALLING 1033 "Installing"
  76. LangString INSTALLING 2052 "正在安装"
  77. LangString INSTALLING 1028 "安裝中"`;
  78. }
  79. protected async makeGeneral(): Promise<string> {
  80. return `${ NsisComposer.DIVIDER }
  81. #
  82. # General
  83. #
  84. ${ NsisComposer.DIVIDER }
  85. Unicode true
  86. Name "\${_APPNAME}"
  87. Caption "\${_APPNAME}"
  88. BrandingText "\${_APPNAME} \${_VERSION}"
  89. ${
  90. this.options.icon
  91. ? `Icon "${ win32.normalize(resolve(this.options.icon)) }"`
  92. : ''
  93. }
  94. ${
  95. this.options.unIcon
  96. ? `UninstallIcon "${ win32.normalize(resolve(this.options.unIcon)) }"`
  97. : ''
  98. }
  99. SetCompressor ${ this.options.solid ? '/SOLID' : '' } ${ this.options.compression }
  100. OutFile "\${_OUTPUT}"
  101. InstallDir "${ this.options.installDirectory }"
  102. InstallDirRegKey HKCU "Software\\\${_APPNAME}" "InstallDir"
  103. RequestExecutionLevel user
  104. XPStyle on`;
  105. }
  106. protected async makeModernUI(): Promise<string> {
  107. return `${ NsisComposer.DIVIDER }
  108. #
  109. # Modern UI
  110. #
  111. ${ NsisComposer.DIVIDER }
  112. !include "MUI2.nsh"
  113. Function CreateDesktopShortcut
  114. CreateShortcut "$DESKTOP\\\${_APPNAME}.lnk" "$INSTDIR\\\${_APPNAME}.exe"
  115. FunctionEnd
  116. !define MUI_STARTMENUPAGE_REGISTRY_ROOT "HKCU"
  117. !define MUI_STARTMENUPAGE_REGISTRY_KEY "Software\\\${_APPNAME}"
  118. !define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "StartMenuFolder"
  119. !define MUI_FINISHPAGE_SHOWREADME ""
  120. !define MUI_FINISHPAGE_SHOWREADME_TEXT "$(CREATE_DESKTOP_SHORTCUT)"
  121. !define MUI_FINISHPAGE_SHOWREADME_FUNCTION CreateDesktopShortcut
  122. Var StartMenuFolder
  123. !define MUI_FINISHPAGE_RUN "$INSTDIR\\\${_APPNAME}.exe"
  124. !insertmacro MUI_PAGE_WELCOME
  125. !insertmacro MUI_PAGE_DIRECTORY
  126. !insertmacro MUI_PAGE_STARTMENU "Application" $StartMenuFolder
  127. !insertmacro MUI_PAGE_INSTFILES
  128. !insertmacro MUI_PAGE_FINISH
  129. !insertmacro MUI_UNPAGE_WELCOME
  130. !insertmacro MUI_UNPAGE_CONFIRM
  131. !insertmacro MUI_UNPAGE_INSTFILES
  132. !insertmacro MUI_UNPAGE_FINISH
  133. ${
  134. this.options.languages.map((language) => {
  135. return `!insertmacro MUI_LANGUAGE "${ language }"`;
  136. }).join('\n')
  137. }
  138. ${
  139. this.options.languages.length > 1
  140. ? `!insertmacro MUI_RESERVEFILE_LANGDLL`
  141. : ''
  142. }`;
  143. }
  144. protected async makeVersioning(): Promise<string> {
  145. return `${ NsisComposer.DIVIDER }
  146. #
  147. # Versioning
  148. #
  149. ${ NsisComposer.DIVIDER }
  150. VIProductVersion "\${_VERSION}"
  151. VIAddVersionKey /LANG=0 "ProductName" "\${_APPNAME}"
  152. VIAddVersionKey /LANG=0 "CompanyName" "\${_COMPANYNAME}"
  153. VIAddVersionKey /LANG=0 "FileDescription" "$\{_DESCRIPTION}"
  154. VIAddVersionKey /LANG=0 "FileVersion" "\${_VERSION}"
  155. VIAddVersionKey /LANG=0 "LegalCopyright" "\${_COPYRIGHT}"`;
  156. }
  157. protected async makeHooks(): Promise<string> {
  158. return `${ NsisComposer.DIVIDER }
  159. #
  160. # Hooks
  161. #
  162. ${ NsisComposer.DIVIDER }
  163. Function .onInit
  164. ${
  165. this.options.languages.length > 1
  166. ? `!insertmacro MUI_LANGDLL_DISPLAY`
  167. : ''
  168. }
  169. FunctionEnd`;
  170. }
  171. protected async makeInstallSection(): Promise<string> {
  172. return `${ NsisComposer.DIVIDER }
  173. #
  174. # Install
  175. #
  176. ${ NsisComposer.DIVIDER }
  177. Section -Install
  178. SetShellVarContext current
  179. SetOverwrite ifnewer
  180. WriteRegStr HKCU "Software\\\${_APPNAME}" "InstallDir" "$INSTDIR"
  181. ${ await this.makeInstallerFiles() }
  182. !insertmacro MUI_STARTMENU_WRITE_BEGIN "Application"
  183. CreateDirectory "$SMPROGRAMS\\$StartMenuFolder"
  184. CreateShortcut "$SMPROGRAMS\\$StartMenuFolder\\\${_APPNAME}.lnk" "$INSTDIR\\\${_APPNAME}.exe"
  185. CreateShortcut "$SMPROGRAMS\\$StartMenuFolder\\Uninstall.lnk" "$INSTDIR\\Uninstall.exe"
  186. !insertmacro MUI_STARTMENU_WRITE_END
  187. WriteUninstaller "$INSTDIR\\Uninstall.exe"
  188. SectionEnd`;
  189. }
  190. protected async makeUninstallSection(): Promise<string> {
  191. return `${ NsisComposer.DIVIDER }
  192. #
  193. # Uninstall
  194. #
  195. ${ NsisComposer.DIVIDER }
  196. Section Uninstall
  197. # FIXME: Remove installed files only.
  198. RMDir /r "$INSTDIR"
  199. !insertmacro MUI_STARTMENU_GETFOLDER "Application" $StartMenuFolder
  200. Delete "$SMPROGRAMS\\$StartMenuFolder\\\${_APPNAME}.lnk"
  201. Delete "$SMPROGRAMS\\$StartMenuFolder\\Uninstall.lnk"
  202. RMDir "$SMPROGRAMS\\$StartMenuFolder"
  203. Delete "$DESKTOP\\\${_APPNAME}.lnk"
  204. DeleteRegKey HKCU "Software\\\${_APPNAME}"
  205. SectionEnd`;
  206. }
  207. protected async makeInstallerFiles(): Promise<string> {
  208. return `SetOutPath "$INSTDIR"
  209. FILE /r .\\*.*`;
  210. }
  211. }