Chapter 09無料公開

関連付けられたファイルから Electron アプリを起動する (macOS)

Kei Touge
Kei Touge
2021.09.18に更新

https://www.electronjs.org/docs/api/app#event-will-finish-launching

ファイルパスの取得

メインプロセス

src/main.ts
import path from 'path';
import { app, BrowserWindow } from 'electron';

/**
 * webContents よりも先に存在していないといけないので
 * グローバル変数とする
 */
let openfile: string | null = null;

const createWindow = () => {
  const mainWindow = new BrowserWindow({
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
    },
  });

  // webContents が立ち上がったら、グローバル変数を回収する
  mainWindow.webContents.once('did-finish-load', () => {
    // もし openfile が null でなかったら・・・
    if (openfile) {
      // レンダラープロセスへファイルパスを送信
      mainWindow.webContents.send('open-file', openfile);

      // グローバル変数を初期化
      openfile = null;
    }
  });

  mainWindow.loadFile('dist/index.html');
};

/**
 * macOS では、'ready' イベントよりも先に発火する
 * 'will-finish-launching' イベントでしか
 * ファイルパスを取得できない
 */
app.once('will-finish-launching', () => {
  // macOS のみに存在する 'open-file' イベント
  app.once('open-file', (e, filepath) => {
    // 必須!
    e.preventDefault();

    /**
     * まだ webContents が立ち上がってないので
     * いったんグローバル変数へ預ける
     */
    openfile = filepath;
  });
});

app.once('ready', createWindow);
app.once('window-all-closed', () => app.quit());

プリロードスクリプト

src/preload.ts
import { contextBridge, ipcRenderer } from 'electron';

contextBridge.exposeInMainWorld('myAPI', {
  openFile: (listener: (_e: Event, filepath: string) => void) =>
    ipcRenderer.on('open-file', listener),
});

型定義ファイル

src/global.d.ts
declare global {
  interface Window {
    myAPI: Sandbox;
  }
}

export interface Sandbox {
  openFile: (
    listener: (_e: Event, filepath: string) => void
  ) => Electron.IpcRenderer;
}

レンダラープロセス

src/app.ts
const { myAPI } = window;
const text = document.getElementById('text');

const onOpenFile = (_e: Event, filepath: string) => {
  if (!filepath) return;
  if (text) text.textContent = filepath;
};

myAPI.openFile(onOpenFile);

起動テスト

パッケージングする。

bash
% node ./build.js
  • electron-builder  version=22.11.7 os=20.5.0
  • description is missed in the package.json  appPackageFile=/Users/zenn/ts-zenn/package.json
  • writing effective config  file=release/builder-effective-config.yaml
  • packaging       platform=darwin arch=x64 electron=13.1.2 appOutDir=release/mac
  • default Electron icon is used  reason=application icon is not set
  • skipped macOS code signing  reason=identity explicitly is set to null
  • building        target=macOS zip arch=x64 file=release/zenn-1.0.0-mac.zip
  • building        target=DMG arch=x64 file=release/zenn-1.0.0.dmg
  • building block map  blockMapFile=release/zenn-1.0.0.dmg.blockmap
  • building embedded block map  file=release/zenn-1.0.0-mac.zip

プロジェクトフォルダ/release/mac へ出力された app ファイルへ画像ファイルをドラッグ&ドロップ。