NsisComposer.ts 7.0 KB

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