コンテンツにスキップ
Tauri

Single Instance(インスタンスの単一実行)

《訳注》

Plugin 説明内容の英語表記部分について Plugin の各章は、原文データからページ内容の一部が自動生成されているため、英語表記のままの部分があります。

GitHub crates.io
API Reference

「Single Instance」プラグインを使用して、あなたの Tauri アプリのインスタンスが一度に一つだけ実行されていることを保証します。

This plugin requires a Rust version of at least 1.77.2

Platform Level Notes
windows
linux
macos
android
ios

はじめに、「Single Instance」プラグインをインストールしてください。

自分のプロジェクトのパッケージ・マネージャーを使用して依存関係を追加します:

npm run tauri add single-instance

このプラグインがもうすでにインストールおよび初期化されていれば、すぐに正しく動作するはずです。ただし、init() メソッドを使用して機能を拡張することもできます。

プラグインの init() メソッドは、新しいアプリのインスタンスが開始されたときに呼び出される「クロージャ」を受け取りますが、このクロージャはプラグインによって閉じられます。 このクロージャには三つの引数があります:

  1. app: アプリケーションの AppHandle
  2. args: この新しいインスタンスを開始するためにユーザーによって渡された引数のリスト。
  3. cwd: 「CWD」(現在の作業ディレクトリ Current Working Directory)は、新しいアプリケーション・インスタンスが起動されたディレクトリを示します。
《訳注》

クロージャ closure: 訳「関数閉包」。クロージャとは関数をまとめて/囲んで(バンドル)、その周囲の状態(レキシカル環境)への参照と組み合わせたもので、クロージャは関数にその外側のスコープへアクセスする機能を提供します(プログラム内で環境を共有するための仕組み)。JavaScript では、関数が作成されるたびに、つまり関数の作成時点で、クロージャが作成されます。《mdn; wikipedia

レキシカル環境 lexical environment: 訳「語彙環境」。「レキシカル環境」は仕様上の隠れた内部の関連オブジェクトです(言語仕様の動作説明を行なうための理論上の存在)。このオブジェクトをコード上で取得したり直接操作することはできません。各処理が発生するたびにレキシカル環境は作成され、必要に応じて参照されます。《Javascript.info 静的スコープ wikipedia

そこで、「クロージャ」は以下のようになります:

.plugin(tauri_plugin_single_instance::init(|app, args, cwd| {
// ここに、あなたのコードを記載します...
}))

デフォルトでは、アプリケーションが既に実行されている状態で新しいインスタンスを開始しても、何も実行されません。ユーザーが新しいインスタンスを開こうとしたときに、実行中のインスタンスのウィンドウにフォーカスを当てるには、コールバック・クロージャを以下のように変更してください。

src-tauri/src/lib.rs
use tauri::{AppHandle, Manager};
pub fn run() {
let mut builder = tauri::Builder::default();
#[cfg(desktop)]
{
builder = builder.plugin(tauri_plugin_single_instance::init(|app, args, cwd| {
let _ = app.get_webview_window("main")
.expect("no main window")
.set_focus();
}));
}
builder
.run(tauri::generate_context!())
.expect("error while running tauri application");
}

Linuxでは、「Single Instance」プラグインは DBus を使用して、実行されるインスタンスが一つだけであることを保証します。この処理は、最初のインスタンスの実行開始時に DBus にサービスを発行することで実現しています。 その後、後続のインスタンスが同じサービスを発行しようとしたときに、すでに別のサービスが発行されていた場合には、後続のインスタンスは最初のインスタンスに通知を行なうためにすでにあるサービスに要求を送信して、すぐに終了します。

これは、アプリが deb か rpm のパッケージ、あるいは AppImage としてバンドルされている場合には非常にうまく機能しますが、snap や flatpak のパッケージでは、デフォルトのままでは意図したとおりに機能しません。これは、これらのパッケージが制約のあるサンドボックス環境で実行されており、パッケージのマニフェストで明示的に宣言されていない限り、DBus サービスへの通信のほとんどがブロックされるためです。

《訳注》

DBus Desktop Bus: 「ディー・バス」。メッセージバスと呼ばれる、アプリケーション間でやりとりを行なうための、プロセス間通信 (IPC) 実装の一つ。プロセスの生成期間を調節し、それらのサービスが必要なときに簡単に呼び出すことができるようにします。《wikipedia

以下は、snap および flatpak パッケージで「Single Instance」プラグインを有効化するために必要なアクセス権限を宣言する手順です:

「Single Instance」プラグインは、org.{id}.SingleInstance という名前のサービスを発行します。

{id}tauri.conf.json ファイルの identifier になりますが、ドット (.) とダッシュ (-) は下線 (_) に置き換えられます。

たとえば、あなたの identifiernet.mydomain.MyApp である場合:

  • net_mydomain_MyApp があなたのアプリの {id} であり、
  • org.net_mydomain_MyApp.SingleInstance があなたのアプリの「SingleInstance」サービスの名前になります。

以下に示すように、アプリに snap や flatpak のマニフェストで DBus サービスを使用することを許可するためには、「サービス名」が必要になります。

あなたの「snapcraft.yml」ファイルで、「Single Instance」サービス用の「プラグ」と「スロット」を宣言し、アプリの宣言でその両方を使用します:

snapcraft.yml
# ...
slots:
single-instance:
interface: dbus
bus: session
name: org.net_mydomain_MyApp.SingleInstance # net_mydomain_MyApp の部分は「あなたのアプリ ID」に変更してください。
plugs:
single-instance-plug:
interface: dbus
bus: session
name: org.net_mydomain_MyApp.SingleInstance # net_mydomain_MyApp の部分は「あなたのアプリ ID」に変更してください。
# .....
apps:
my-app:
# ...
plugs:
# ....
- single-instance-plug
slots:
# ...
- single-instance
# ....

これにより、あなたのアプリは、期待通りに「Single Instance」プラグインが DBus サービスとの間でリクエストを送受信できるようになります。

あなたの flatpak マニフェスト・ファイル(your.app.id.yml または your.app.id.json)で、「サービス名」を含む --talk-name--own-name の終了引数(finish args)を宣言します:

net.mydomain.MyApp.yml
# ...
finish-args:
- --socket=wayland
- --socket=fallback-x11
- --device=dri
- --share=ipc
# ....
- --talk-name=org.net_mydomain_MyApp.SingleInstance # net_mydomain_MyApp の部分は「あなたのアプリ ID」に変更してください。
- --own-name=org.net_mydomain_MyApp.SingleInstance # net_mydomain_MyApp の部分は「あなたのアプリ ID」に変更してください。
# ...

これにより、あなたのアプリで、期待どおりに、「Single Instance」プラグインが DBus サービスとの間でリクエストを送受信できるようになります。

このプラグインには現在 JavaScript API がないため、これを使用するための capabilities の設定を行なう必要はありません。

【※ この日本語版は、「Nov 3, 2025 英語版」に基づいています】


© 2025 Tauri Contributors. CC-BY / MIT