win32.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. 'use strict'
  2. const debug = require('debug')('electron-packager')
  3. const path = require('path')
  4. const pify = require('pify')
  5. const App = require('./platform')
  6. const common = require('./common')
  7. function updateWineMissingException (err) {
  8. if (err && err.code === 'ENOENT' && err.syscall === 'spawn wine') {
  9. err.message = 'Could not find "wine" on your system.\n\n' +
  10. 'Wine is required to use the appCopyright, appVersion, buildVersion, icon, and \n' +
  11. 'win32metadata parameters for Windows targets.\n\n' +
  12. 'Make sure that the "wine" executable is in your PATH.\n\n' +
  13. 'See https://github.com/electron-userland/electron-packager#building-windows-apps-from-non-windows-platforms for details.'
  14. }
  15. return err
  16. }
  17. class WindowsApp extends App {
  18. get originalElectronName () {
  19. return 'electron.exe'
  20. }
  21. get newElectronName () {
  22. return `${common.sanitizeAppName(this.executableName)}.exe`
  23. }
  24. get electronBinaryPath () {
  25. return path.join(this.stagingPath, this.newElectronName)
  26. }
  27. generateRceditOptionsSansIcon () {
  28. const win32metadata = Object.assign({
  29. FileDescription: this.opts.name,
  30. InternalName: this.opts.name,
  31. OriginalFilename: this.newElectronName,
  32. ProductName: this.opts.name
  33. }, this.opts.win32metadata)
  34. let rcOpts = {'version-string': win32metadata}
  35. if (this.opts.appVersion) {
  36. rcOpts['product-version'] = rcOpts['file-version'] = this.opts.appVersion
  37. }
  38. if (this.opts.buildVersion) {
  39. rcOpts['file-version'] = this.opts.buildVersion
  40. }
  41. if (this.opts.appCopyright) {
  42. rcOpts['version-string'].LegalCopyright = this.opts.appCopyright
  43. }
  44. const manifestProperties = ['application-manifest', 'requested-execution-level']
  45. for (const manifestProperty of manifestProperties) {
  46. if (win32metadata[manifestProperty]) {
  47. rcOpts[manifestProperty] = win32metadata[manifestProperty]
  48. }
  49. }
  50. return rcOpts
  51. }
  52. getIconPath () {
  53. if (!this.opts.icon) {
  54. return Promise.resolve()
  55. }
  56. return this.normalizeIconExtension('.ico')
  57. }
  58. needsRcedit () {
  59. return this.opts.icon || this.opts.win32metadata || this.opts.appCopyright || this.opts.appVersion || this.opts.buildVersion
  60. }
  61. runRcedit () {
  62. /* istanbul ignore if */
  63. if (!this.needsRcedit()) {
  64. return Promise.resolve()
  65. }
  66. const rcOpts = this.generateRceditOptionsSansIcon()
  67. return this.getIconPath()
  68. .then(icon => {
  69. // Icon might be omitted or only exist in one OS's format, so skip it if normalizeExt reports an error
  70. if (icon) {
  71. rcOpts.icon = icon
  72. }
  73. debug(`Running rcedit with the options ${JSON.stringify(rcOpts)}`)
  74. return pify(require('rcedit'))(this.electronBinaryPath, rcOpts)
  75. }).catch(err => {
  76. /* istanbul ignore next */
  77. throw updateWineMissingException(err)
  78. })
  79. }
  80. create () {
  81. return this.initialize()
  82. .then(() => this.renameElectron())
  83. .then(() => this.copyExtraResources())
  84. .then(() => this.runRcedit())
  85. .then(() => this.move())
  86. }
  87. }
  88. module.exports = {
  89. App: WindowsApp,
  90. updateWineMissingException: updateWineMissingException
  91. }