3

I have an WPF application called app1 which has a windows named window1. When the user clicks the close button of window1, the app does not close but the window1 hides (this.hide()).

I want to check if another instance of the application is already running when it is started; if so, I want to show the already running instance and terminate the new one.

How can I do that?

I know how to check the process and how to close the current app but I don't know how to show a window from another WPF process which is running...

In my App startup event I do this :

private void Application_Startup(object sender, StartupEventArgs e)
{
    if(Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName).Count() > 1)
    {
        Application.Current.Shutdown(0);
    }
}  
Adam
  • 15,537
  • 2
  • 42
  • 63
mahdavipanah
  • 600
  • 5
  • 21

2 Answers2

6

A typical approach to this is to use a Mutex. This allows you to prevent a second instance from being started (or rather, detect it within the second instance of the application).

At that point, you can notify the original application instance to "show" itself. Here is a good article describing the entire process in detail (though using Windows Forms).

For a WPF application, you'll need to put this logic in the Application's startup logic, and add an HwndSourceHook to process the windows message in your WPF window which you want to have show.

Community
  • 1
  • 1
Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
2

I found how to do the work!

My problem solved with "Reed Copsey" help and with Windows SendMessage API. for doing this thing I wrote these codes in my window1.xaml.cs file :


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows.Interop;


namespace app1
{
    public partial class window1: Window
    {
        public window1()
        {
            InitializeComponent();            
        }
        private void window1_Loaded(object sender, RoutedEventArgs e)
        {
            HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
            source.AddHook(new HwndSourceHook(WndProc));
        }
        private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            System.Windows.Forms.Message m = System.Windows.Forms.Message.Create(hwnd, msg, wParam, lParam);
            if (m.Msg == WM_COPYDATA)
            {
                // Get the COPYDATASTRUCT struct from lParam.
                COPYDATASTRUCT cds = (COPYDATASTRUCT)m.GetLParam(typeof(COPYDATASTRUCT));

                // If the size matches
                if (cds.cbData == Marshal.SizeOf(typeof(MyStruct)))
                {
                    // Marshal the data from the unmanaged memory block to a 
                    // MyStruct managed struct.
                    MyStruct myStruct = (MyStruct)Marshal.PtrToStructure(cds.lpData,
                        typeof(MyStruct));

                    // Display the MyStruct data members.
                    if (myStruct.Message == "Show Up")
                    {
                        this.Show();
                    }
                }
            }
            return IntPtr.Zero;
        }

        internal const int WM_COPYDATA = 0x004A;

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        internal struct MyStruct
        {
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
            public string Message;
        }
        [StructLayout(LayoutKind.Sequential)]
        internal struct COPYDATASTRUCT
        {
            public IntPtr dwData;       // Specifies data to be passed
            public int cbData;          // Specifies the data size in bytes
            public IntPtr lpData;       // Pointer to data to be passed
        }


    }
}


And I wrote these codes in my App.xaml.cs :


using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Windows;
using System.Windows.Threading;
using System.Runtime.InteropServices;
using System.Security;

namespace app1
{    
    public partial class App : Application
    {       
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        internal struct MyStruct
        {
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
            public string Message;
        }



        internal const int WM_COPYDATA = 0x004A;
        [StructLayout(LayoutKind.Sequential)]
        internal struct COPYDATASTRUCT
        {
            public IntPtr dwData;       // Specifies data to be passed
            public int cbData;          // Specifies the data size in bytes
            public IntPtr lpData;       // Pointer to data to be passed
        }
        [SuppressUnmanagedCodeSecurity]
        internal class NativeMethod
        {            
            [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            public static extern IntPtr SendMessage(IntPtr hWnd, int Msg,
                IntPtr wParam, ref COPYDATASTRUCT lParam);


            [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
        }

        private void Application_Startup(object sender, StartupEventArgs e)
        {            
            if (System.Diagnostics.Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName).Count() > 1)
            {
                IntPtr hTargetWnd = NativeMethod.FindWindow(null, "window1");
                if (hTargetWnd == IntPtr.Zero)
                {                    
                    return;
                }
                MyStruct myStruct;
                myStruct.Message = "Show Up";
                int myStructSize = Marshal.SizeOf(myStruct);
                IntPtr pMyStruct = Marshal.AllocHGlobal(myStructSize);
                try
                {
                    Marshal.StructureToPtr(myStruct, pMyStruct, true);

                    COPYDATASTRUCT cds = new COPYDATASTRUCT();
                    cds.cbData = myStructSize;
                    cds.lpData = pMyStruct;
                    NativeMethod.SendMessage(hTargetWnd, WM_COPYDATA, new IntPtr() , ref cds);

                    int result = Marshal.GetLastWin32Error();
                    if (result != 0)
                    {                       
                    }
                }
                finally
                {
                    Marshal.FreeHGlobal(pMyStruct);
                }
                Application.Current.Shutdown(0);
            }            
        }  

    }
}

And that's it. :D

mahdavipanah
  • 600
  • 5
  • 21