XORveR.com の日記

XORveR.com の公式ブログです。

多重起動しないアプリを作ってみた。

まえがき

Common.Util.IPC の使用法のサンプルです。

メリット

単一のインスタンスで実行するアプリケーションを容易に開発できます。

サンプルプロジェクト

Unique プロジェクト

動作について

これを実行すると、多重起動を検知して後続での実行時引数を先行する実行に送信して終了します。
サンプルは実行時引数を接続して MessageBox に出します。

ソースコード

App.xaml.cs

using System;
using System.Windows;
using Common.Util;
using Common.Util.IPC;

namespace Unique {
	/// <summary>
	/// App.xaml の相互作用ロジック
	/// </summary>
	public partial class App : Application, IDisposable {
		private UniqueApplicationInstance unique;
		private MainWindow window;
		private LifeCycleManager lifecycles = new LifeCycleManager();

		public App() {
			Startup += Application_Startup;
			Exit += Application_Exit;
		}

		private void Application_Startup(object sender, StartupEventArgs e) {
			lifecycles.Register(
				(o) => {
					unique = new UniqueApplicationInstance();
				},
				(o) => {
					unique.Dispose();
					unique = null;
				}
			);
			if (unique.IsUniqueApplication == false) {
				// コマンドライン引数を送信
				unique.RaiseStartupNextInstance(e.Args);
				// 終了
				Shutdown();
			} else {
				lifecycles.Register(
					(o) => { Logger.GetLogger().Info("Application Startup"); },
					(o) => { Logger.GetLogger().Info("Application Shutdown"); }
				);

				// メインウィンドウ作成
				lifecycles.Register(
					(o) => {
						window = new MainWindow();
					},
					(o) => {
						window = null;
					}
				);

				// ウィンドウ表示
				window.Show();
				// コマンドライン引数の受信イベントを登録
				unique.OnNextInstanceStartupDetected += NextInstanceStartup_Detected;
			}
		}
		private void Application_Exit(object sender, ExitEventArgs e) {
			Dispose();
		}

		/// <summary>
		/// 多重起動したインスタンスからコマンドライン引数が送られてきた
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void NextInstanceStartup_Detected(object sender, StartupNextInstanceEventArgs e) {
			string str = "";
			foreach (object o in e.Parameters) {
				str += o.ToString() + " ";
			}
			MessageBox.Show(str.TrimEnd());
		}

		#region IDisposable Support
		private bool disposedValue = false;
		protected virtual void Dispose(bool disposing) {
			if (!disposedValue) {
				disposedValue = true;
				if (disposing) {
					lifecycles.Dispose();
				}
			}
		}
		public void Dispose() {
			Dispose(true);
		}
		#endregion
	}
}