これは、単一インスタンスの WPF アプリケーションを作成するためにこれまでに実装したコードです。
#region Using Directives
using System;
using System.Globalization;
using System.Reflection;
using System.Threading;
using System.Windows;
using System.Windows.Interop;
#endregion
namespace MyWPF
{
public partial class MainApplication : Application, IDisposable
{
#region Members
private Int32 m_Message;
private Mutex m_Mutex;
#endregion
#region Methods: Functions
private IntPtr HandleMessages(IntPtr handle, Int32 message, IntPtr wParameter, IntPtr lParameter, ref Boolean handled)
{
if (message == m_Message)
{
if (MainWindow.WindowState == WindowState.Minimized)
MainWindow.WindowState = WindowState.Normal;
Boolean topmost = MainWindow.Topmost;
MainWindow.Topmost = true;
MainWindow.Topmost = topmost;
}
return IntPtr.Zero;
}
private void Dispose(Boolean disposing)
{
if (disposing && (m_Mutex != null))
{
m_Mutex.ReleaseMutex();
m_Mutex.Close();
m_Mutex = null;
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
#region Methods: Overrides
protected override void OnStartup(StartupEventArgs e)
{
Assembly assembly = Assembly.GetExecutingAssembly();
Boolean mutexCreated;
String mutexName = String.Format(CultureInfo.InvariantCulture, "Local\\{{{0}}}{{{1}}}", assembly.GetType().GUID, assembly.GetName().Name);
m_Mutex = new Mutex(true, mutexName, out mutexCreated);
m_Message = NativeMethods.RegisterWindowMessage(mutexName);
if (!mutexCreated)
{
m_Mutex = null;
NativeMethods.PostMessage(NativeMethods.HWND_BROADCAST, m_Message, IntPtr.Zero, IntPtr.Zero);
Current.Shutdown();
return;
}
base.OnStartup(e);
MainWindow window = new MainWindow();
MainWindow = window;
window.Show();
HwndSource.FromHwnd((new WindowInteropHelper(window)).Handle).AddHook(new HwndSourceHook(HandleMessages));
}
protected override void OnExit(ExitEventArgs e)
{
Dispose();
base.OnExit(e);
}
#endregion
}
}
すべてが完璧に機能します...しかし、私はそれについていくつかの疑問を持っています。私のアプローチをどのように改善できるかについて、あなたの提案を受け取りたいと思います.
1)メンバー ( )IDisposable
を使用していたため、コード分析からインターフェイスを実装するように求められました。私の実装は十分ですか?呼び出されることはないので、避けるべきですか?IDisposable
Mutex
Dispose()
2)m_Mutex = new Mutex(true, mutexName, out mutexCreated);
結果を使用して確認するか、使用してから確認するm_Mutex = new Mutex(false, mutexName);
方が良いm_Mutex.WaitOne(TimeSpan.Zero, false);
ですか?マルチスレッドの場合、つまり...
3) RegisterWindowMessage
API 呼び出しは返されるはずUInt32
ですが、メッセージ値としてHwndSourceHook
のみ受け入れInt32
られます... 予期しない動作 (結果が よりも大きいなど) について心配する必要がありますInt32.MaxValue
か?
4)OnStartup
オーバーライドでは...base.OnStartup(e);
別のインスタンスが既に実行されていて、アプリケーションをシャットダウンする場合でも実行する必要がありますか?
5) 値を設定する必要のない既存のインスタンスを最上位に移動するより良い方法はありTopmost
ますか? たぶんActivate()
?
6) 私のアプローチに欠陥があると思いますか? マルチスレッド、不適切な例外処理などに関するものはありますか? たとえば... と の間OnStartup
でアプリケーションがクラッシュした場合はどうなりOnExit
ますか?