2008年8月21日
Compact Framework+C#で二重起動防止
まぁ、わざわざ載せておくほどでもないんですけど…自分用メモ。
Windows CE上のC#アプリケーションで二重起動を防止したかった。ググってみた、例によってWindowsでのページが引っかかる。例えば以下のページ…非常に親切に書かれてる。もちろん、WindowsというかCompactじゃない.NET Frameworkならコレでバッチリ
でも、Compact Frameworkでは…上記ページの最初のアプローチ「現在起動しているプロセスを調べる方法」では、System.Diagnostics.ProcessクラスにGetProcessesByNameメソッドがない
ついでに言うと、ProcessNameプロパティもない
仕方ないので、上記ページの次のアプローチ「Mutexを使用する方法」を試す。Mutexを使う方法は以下のページのコードの方が良いと思ったのでコチラを試す(基本は同じですけど…ReleaseMutexとかチャンとしてたので)。
一応、先にCompact Frameworkでクラスやメソッドがあることを確認(習慣になりつつあります)
大丈夫みたい。じゃぁ、コンパイル………ありゃエラー
どこで…ぎゃあ~Mutexのコンストラクタに2引数のものがない。
うぐぁ~コンストラクタの引数まで確認してなかったよ
仕方ないので、ググってみるとみなさん同じようなこと(2引数のコンストラクタがないと)を書いている。結局、P/InvokeでCreateMutexを使えと
と言うことで、Compact Framework+VB.NET版は以下のページで見つけたけど…C#版がなかったのでコードをペタっと貼っておく。
using HANDLE = System.IntPtr; static class Program { [MTAThread] static void Main() { HANDLE hMutex = CreateMutex(IntPtr.Zero, false, Assembly.GetExecutingAssembly().GetName().Name); if (GetLastError() != ERROR_ALREADY_EXISTS) { Application.Run(new Form1()); } else { MessageBox.Show("アプリケーションは既に起動しています。"); } ReleaseMutex(hMutex); CloseHandle(hMutex); } private const int ERROR_ALREADY_EXISTS = 183; [DllImport("coredll.dll", SetLastError = true)] private static extern HANDLE CreateMutex(IntPtr lpMutexAttributes, bool bInitiaOwner, string lpName); [DllImport("coredll.dll")] private static extern int GetLastError(); [DllImport("coredll.dll")] private static extern bool ReleaseMutex(HANDLE hMutex); [DllImport("coredll.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Auto)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool CloseHandle(HANDLE hObject); }
適当な部分はよしなに
ReleaseMutexやCloseMutexは引数がIntPtr.Zeroでも問題ないようなので常に呼び出してます。
GotDotNetにCompact Frameworkでの二重起動防止のサンプルが在ったようなので…そちらの方が良い可能性が高いです。でも、見つけられなかったのよね
しかし、Microsoftさま…Mutexに2引数(名前付きMutex)のコンストラクタを実装するのは、そんなに大変なのでしょうか
それともコレを実装するとCompact Frameworkが肥大化するのでしょうか
まぁ、何でも要求に沿って入れていけばCompactじゃなくなるので、取捨選択は重要だと思いますけど…。
TrackBack URL :
