多重起動を禁止し起動アプリに引数を渡す方法です。テキストエディタだと定番の処理ですね。プロセス間通信を利用しています。参照設定に System.Runtime.Remoting を追加します。自作エディタもこの方法で実装しています。
サンプルソース
IRemoteObject.cs
多重起動時に実行するメソッドを定義します。
namespace Test {
public interface IRemoteObject {
void StartupNextInstance(params object[] parameters);
}
}
Form1.cs
多重起動を禁止するフォームです。最小化している場合は元に戻します。そしてウィンドウを最前面に表示します。
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace Test {
public partial class Form1 : Form, IRemoteObject {
[DllImport("user32.dll")]
public static extern bool IsIconic(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern int SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
// 画面を元の大きさに戻す
public const int SW_RESTORE = 9;
/// <summary>
/// コンストラクタ
/// </summary>
public Form1() {
InitializeComponent();
}
/// <summary>
/// 多重起動時に呼ばれるイベント
/// </summary>
/// <param name="parameters"></param>
/// <returns></returns>
public void StartupNextInstance(params object[] parameters) {
// メイン・ウィンドウが最小化されていれば元に戻す
if (IsIconic(this.Handle)) {
ShowWindowAsync(this.Handle, SW_RESTORE);
}
// メイン・ウィンドウを最前面に表示する
SetForegroundWindow(this.Handle);
string[] args = (string[])parameters[0];
MessageBox.Show("既に起動しています。引数の数:" + args.Length.ToString());
}
}
}
Program.cs
初回は普通に起動します。すでに起動している場合は引数を Form1 に渡します。
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Ipc;
using System.Runtime.Remoting.Lifetime;
using System.Threading;
using System.Windows.Forms;
namespace Test {
static class Program {
/// <summary>
/// アプリケーションのメイン エントリ ポイントです。
/// </summary>
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
string APP_NAME = Application.ProductName;
string OBJECT_NAME = "Form1";
string URL = "ipc://" + Application.ProductName + "/" + OBJECT_NAME;
bool createdNew = false;
Mutex mutex = new Mutex(true, APP_NAME, out createdNew);
// 初回起動時
if (createdNew) {
Form1 f = new Form1();
LifetimeServices.LeaseTime = TimeSpan.Zero;
LifetimeServices.RenewOnCallTime = TimeSpan.Zero;
IpcChannel ipc = new IpcChannel(APP_NAME);
ChannelServices.RegisterChannel(ipc, false);
RemotingServices.Marshal(f, OBJECT_NAME);
Application.Run(f);
// 多重起動時
} else {
IRemoteObject remoteObject = (IRemoteObject)RemotingServices.Connect(typeof(IRemoteObject), URL);
// 引数を渡す
remoteObject.StartupNextInstance(new object[] { Environment.GetCommandLineArgs() });
}
}
}
}
おわりに
多重起動は Mutex を使う方法がありますが、パラメータを渡せないのでプロセス間通信を利用してみました。
コメント