Click here to Skip to main content
15,881,675 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have a single instance WPF app
if user runs it twice I stop second and show first instance to user
but the problem is procces have MainWindowHandle not ActiveWindowHandle
I mean if user open second windows of app , mainwindows will be hide and second will be visible
so I need to get Handle of ActiveWindow not MainWindow
My code is in what I have tried section

What I have tried:

C#
    public sealed class SingleInstance
    {
        public static bool AlreadyRunning()
        {
            bool running = false;
            try
            {
                // Getting collection of process  
                Process currentProcess = Process.GetCurrentProcess();

                // Check with other process already running   
                foreach (var p in Process.GetProcesses())
                {
                    if (p.Id != currentProcess.Id) // Check running process   
                    {
                        if (p.ProcessName.Equals(currentProcess.ProcessName) == true)
                        {
                            running = true;
                            IntPtr hFound = p.MainWindowHandle;
                            if (User32API.IsIconic(hFound)) // If application is in ICONIC mode then  
                                User32API.ShowWindow(hFound, User32API.SW_RESTORE);
                            User32API.SetForegroundWindow(hFound); // Activate the window, if process is already running  
                            break;
                        }
                    }
                }
            }
            catch { }
            return running;
        }
    }
    public class User32API
    {
        [DllImport("User32.dll")]
        public static extern bool IsIconic(IntPtr hWnd);

        [DllImport("User32.dll")]
        public static extern bool SetForegroundWindow(IntPtr hWnd);

        [DllImport("User32.dll")]
        public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
        public const int SW_RESTORE = 9;
    }
//Usage
//on start up I check
if (SingleInstance.AlreadyRunning())
{
System.Windows.Application.Current.Shutdown(0);
}
Posted
Updated 29-Jul-21 17:51pm

Use a Mutex [^], or use other techniques described here [^], or, here [^]
 
Share this answer
 
I solve this by read all active windows
then check if this windows belongs to this process
if yes show it
you can see even windows titles to be sure the code work correctly

C#
private static IntPtr GetActiveWindowHandle(IntPtr mainWindowHandle, int pId)
        {
            List<IntPtr> AllWindowsHandl = GetAllChildHandles(mainWindowHandle);
            List<IntPtr> ActiveWindowsHandl = new List<IntPtr>();
            List<string> ActiveWindowsName =  new List<string>();
            foreach (IntPtr i in AllWindowsHandl)
            {
                int proccessId = 0;
                if (User32API.IsWindowVisible(i))
                {
                    User32API.GetWindowThreadProcessId(i, out proccessId);
                    if (pId == proccessId)
                    {
                        ActiveWindowsHandl.Add(i);
                        StringBuilder title = new StringBuilder(256);

                        int x = User32API.GetWindowText(i, title, 256);
                        ActiveWindowsName.Add(title.ToString());
                    }

                }
            }
            if (ActiveWindowsHandl.Count == 1) { return ActiveWindowsHandl[0]; }
            return mainWindowHandle;
        }

        private static List<IntPtr> GetAllChildHandles(IntPtr mainWindowHandle)
        {
            List<IntPtr> childHandles = new List<IntPtr>();

            GCHandle gcChildhandlesList = GCHandle.Alloc(childHandles);
            IntPtr pointerChildHandlesList = GCHandle.ToIntPtr(gcChildhandlesList);

            try
            {
                EnumWindowProc childProc = new EnumWindowProc(EnumWindow);
                EnumChildWindows(mainWindowHandle, childProc, pointerChildHandlesList);
            }
            finally
            {
                gcChildhandlesList.Free();
            }

            return childHandles;
        }

        private static bool EnumWindow(IntPtr hWnd, IntPtr lParam)
        {
            GCHandle gcChildhandlesList = GCHandle.FromIntPtr(lParam);

            if (gcChildhandlesList == null || gcChildhandlesList.Target == null)
            {
                return false;
            }

            List<IntPtr> childHandles = gcChildhandlesList.Target as List<IntPtr>;
            childHandles.Add(hWnd);

            return true;
        }

//add this to User32API
private delegate bool EnumWindowProc(IntPtr hwnd, IntPtr lParam);
        [DllImport("user32")]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr lParam);
        [DllImport("user32")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool IsWindowVisible(IntPtr hWnd);
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern int GetWindowText(IntPtr hWnd, StringBuilder title, int size);
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern int GetWindowThreadProcessId(IntPtr hWnd, out int processId);
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900