打包后电子托盘图标不显示

Electron Tray Icon doesn't show after once I package

我有一个显示托盘图标的 Electron 应用程序,点击后会显示我的主 window。在开发模式下效果很好,但是当我将它打包(放入 .app 文件)并双击 .app 文件时,菜单的 none 出现了,更重要的是,图标没有出现,所以用户永远看不到我的应用程序。

我正在使用电子 React/Redux 样板 (https://github.com/chentsulin/electron-react-boilerplate)

这是我的 main.dev.js 文件 - 欢迎猜测:

import { app, BrowserWindow, Tray } from 'electron';
import MenuBuilder from './menu';

let mainWindow = null;
let tray;

if (process.env.NODE_ENV === 'production') {
  const sourceMapSupport = require('source-map-support');
  sourceMapSupport.install();
}

if (
  process.env.NODE_ENV === 'development' ||
  process.env.DEBUG_PROD === 'true'
) {
  require('electron-debug')();
  const path = require('path');
  const p = path.join(__dirname, '..', 'app', 'node_modules');
  require('module').globalPaths.push(p);
}

const installExtensions = async () => {
  const installer = require('electron-devtools-installer');
  const forceDownload = !!process.env.UPGRADE_EXTENSIONS;
  const extensions = ['REACT_DEVELOPER_TOOLS', 'REDUX_DEVTOOLS'];

  return Promise.all(
    extensions.map(name => installer.default(installer[name], forceDownload))
  ).catch(console.error);
};

/**
 * Add event listeners...
 */

app.on('window-all-closed', () => {
  // Respect the OSX convention of having the application in memory even
  // after all windows have been closed
  if (process.platform !== 'darwin') {
    app.quit();
  }
});

const getWindowPosition = () => {
  const windowBounds = mainWindow.getBounds();
  const trayBounds = tray.getBounds();

  // Center window horizontally below the tray icon
  const x = Math.round(
    trayBounds.x + trayBounds.width / 2 - windowBounds.width / 2
  );

  // Position window 4 pixels vertically below the tray icon
  const y = Math.round(trayBounds.y + trayBounds.height + 4);

  return { x, y };
};

function createTray() {
  const path = require('path');
  const iconPath = path.join(__dirname, 'confluence.png');
  tray = new Tray(iconPath);
  tray.setToolTip('Confluence Helper');
  tray.on('click', event => {
    toggleWindow();

    // Show devtools when command clicked
    if (mainWindow.isVisible() && process.defaultApp && event.metaKey) {
      mainWindow.openDevTools({ mode: 'detach' });
    }
  });
}
const toggleWindow = () => {
  if (mainWindow.isVisible()) {
    mainWindow.hide();
  } else {
    showWindow();
  }
};

const showWindow = () => {
  const position = getWindowPosition();
  mainWindow.setPosition(position.x, position.y, false);
  mainWindow.show();
  mainWindow.focus();
};

app.on('ready', async () => {
  if (
    process.env.NODE_ENV === 'development' ||
    process.env.DEBUG_PROD === 'true'
  ) {
    await installExtensions();
  }

  mainWindow = new BrowserWindow({
    show: false,
    width: 500,
    height: 728,
    icon: `${__dirname}/confluence.icns`
  });

  mainWindow.loadURL(`file://${__dirname}/app.html`);

  createTray();
  // @TODO: Use 'ready-to-show' event
  //        https://github.com/electron/electron/blob/master/docs/api/browser-window.md#using-ready-to-show-event
  mainWindow.webContents.on('did-finish-load', () => {
    if (!mainWindow) {
      throw new Error('"mainWindow" is not defined');
    }
    if (process.env.START_MINIMIZED) {
      mainWindow.minimize();
    }
  });
  mainWindow.on('blur', () => {
    mainWindow.hide();
  });

  mainWindow.on('closed', () => {
    mainWindow = null;
  });

  const menuBuilder = new MenuBuilder(mainWindow);
  menuBuilder.buildMenu();
});

当我右键单击 .app 文件并选择 "Show Package Contents" 时,我可以看到一个 Contents/Mac 文件夹,里面是一个 unix 可执行文件文件,当我在命令行中 运行 时,它向我展示了一个与我的托盘图标有关的被拒绝的承诺 - 我正在做一个 path.join(__dirname,'icon.png'),结果是错误的路径(console.log(path.join(__dirname,'icon.png')) 救援!

当我将其更改为绝对路径 ('users/myname/app/icon.png') 并重建时,它成功了!

但是,这显然不适用于其他人的计算机 - 它确实适用于我的计算机 (tm),但这还不够好。

要真正修复它,我可能做得太过火了 - 但这对我有用 - 通过创建 NativeImage,使用 path.join(__dirname,'resources','icon.png') 在我传入的内容中。我也在build/files下添加了资源在package.json.

如果你 运行 遇到这种问题,我会建议你做我所做的(显示包内容,等等)来查看打包电子中的问题应用

我在 Windows 上遇到了同样的问题(未在其他操作系统中测试过)。 运行 来自 VSCode 的应用程序时,托盘图标可以正常工作,但在为 Windows 打包后它是不可见的。就像@raingod 的回答一样,我使用的是绝对路径:

//Gets the icon to use in the tray
icon = nativeImage.createFromPath(path.join(__dirname, "build", "32x32.png"))
//Creates the tray
tray = new Tray(icon)

但我发现 问题是我指向“构建”文件夹 中的一个文件,我的应用程序的所有图标都存储在该文件夹中。不知何故,它专门导致了打包应用程序中托盘图标的问题。 所以我只将托盘图标中使用的文件移动到另一个文件夹:“./src/icons/32x32.png”。所以代码看起来像这样:

//Gets the icon to use in the tray
icon = nativeImage.createFromPath(path.join(__dirname, "src", "icons", "32x32.png"))
//Creates the tray
tray = new Tray(icon)

因为其他人可能有同样的问题,所以在这里张贴。所以使用绝对路径,并且不要将图标文件存储在“build”文件夹中。