WPFアプリケーションで二重起動を防ぐ方法(その2)

二重起動されたときの処理では、先に起動されている方を前面に表示したい場合もあります。
例えばWindowsフォームアプリケーションだとこんな感じでできます。

using System;
using System.Diagnostics;
using System.Windows.Forms;

namespace WindowsFormsApplication2
{
    static class Program
    {
        /*
         * Win32APIをP/Invokeで使用するための宣言
         */
        [System.Runtime.InteropServices.DllImport("User32.dll")]
        private static extern int ShowWindow(IntPtr hWnd, int nCmdShow);

        [System.Runtime.InteropServices.DllImport("User32.dll")]
        private static extern bool SetForegroundWindow(IntPtr hWnd);

        private const int SW_SHOWNORMAL = 1;

        /// <summary>
        /// アプリケーションのメイン エントリ ポイントです。
        /// </summary>
        [STAThread]
        static void Main()
        {
            /* 現在のプロセスを取得 */
            Process currentProcess = Process.GetCurrentProcess();

            /* 現在のプロセスと同名のプロセスを取得 */
            Process[] processes = Process.GetProcessesByName(currentProcess.ProcessName);

            foreach (Process p in processes)
            {
                /* 同名の他のプロセスがあれば... */
                if (p.Id != currentProcess.Id)
                {
                    /* ウィンドウを全面に表示する */
                    ShowWindow(p.MainWindowHandle, SW_SHOWNORMAL);
                    SetForegroundWindow(p.MainWindowHandle);
                    return;
                }
            }

            /* 同名の他のプロセスがなければ起動 */
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
}


これをWPFで書く場合、App.xamlにSystem.Windows.ApplicationクラスのStartupのイベントハンドラを宣言して、

<Application x:Class="WpfApplication2.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    StartupUri="Window1.xaml" Startup="Application_Startup">
    <Application.Resources>
    </Application.Resources>
</Application>


App.xaml.csに、アプリケーション起動前にする処理をStartupイベントに実装します。

using System;
using System.Diagnostics;
using System.Windows;

namespace WpfApplication2
{
    /// <summary>
    /// App.xaml の相互作用ロジック
    /// </summary>
    public partial class App : Application
    {
        /*
         * Win32APIをP/Invokeで使用するための宣言
         */
        [System.Runtime.InteropServices.DllImport("User32.dll")]
        private static extern int ShowWindow(IntPtr hWnd, int nCmdShow);

        [System.Runtime.InteropServices.DllImport("User32.dll")]
        private static extern bool SetForegroundWindow(IntPtr hWnd);

        private const int SW_SHOWNORMAL = 1;

        private void Application_Startup(object sender, StartupEventArgs e)
        {
            /* 現在のプロセスを取得 */
            Process currentProcess = Process.GetCurrentProcess();

            /* 現在のプロセスと同名のプロセスを取得 */
            Process[] processes = Process.GetProcessesByName(currentProcess.ProcessName);

            foreach (Process p in processes)
            {
                /* 同名の他のプロセスがあれば... */
                if (p.Id != currentProcess.Id)
                {
                    /* ウィンドウを全面に表示する */
                    ShowWindow(p.MainWindowHandle, SW_SHOWNORMAL);
                    SetForegroundWindow(p.MainWindowHandle);

                    /* 起動を中止してプログラムを終了 */
                    this.Shutdown();
                }
            }
        }
    }
}

これで、二重起動されたときに最初に起動したプロセスを前面に表示することができます。