0

I have a WPF application I can minimize or put it in the system tray.

To put it in the system tray, I minimize and collapse the app and change the icon visibility to be visible in the system tray.

I want to restore the application and put it in the foreground if the user try to open another one (if he didn't see the app icon in the system tray).

For this, I have a mutex (maybe not the safest solution but well...) to check if the app is already running :

    bool mutexCreated;
    _Mutex = new Mutex(true, MODULENAME, out mutexCreated);
    if (!mutexCreated)
    {
        CheckRunningInstance();
        Shutdown();
    }

If the app is already running, I try to get the process linked and forced the restoration :

public static void CheckRunningInstance()
{
    Process current = Process.GetCurrentProcess();
    Process[] processes = Process.GetProcessesByName(current.ProcessName);

    //Loop through the running processes in with the same name
    foreach (Process process in processes)
    {
        //Ignore the current process
        if (process.Id != current.Id)
        {
            //Make sure that the process is running from the exe file.
            if (Assembly.GetExecutingAssembly().Location.Replace("/", "\\") == current.MainModule.FileName)
            {
                //Focus the other process instance.
               // ShowWindow(process.MainWindowHandle, ShowWindowEnum.Show);
               // ShowWindow(process.MainWindowHandle, ShowWindowEnum.ShowNormal);
                ShowWindow(process.MainWindowHandle, ShowWindowEnum.Restore);
                SetForegroundWindow(process.MainWindowHandle);
                
            }
        }
    }
}

The ShowWindowEnum is the basic one :

private enum ShowWindowEnum
{
    Hide = 0,
    ShowNormal = 1, ShowMinimized = 2, ShowMaximized = 3,
    Maximize = 3, ShowNormalNoActivate = 4, Show = 5,
    Minimize = 6, ShowMinNoActivate = 7, ShowNoActivate = 8,
    Restore = 9, ShowDefault = 10, ForceMinimized = 11
};

And the ShowWindow & SetforegroundWindow come from Windows :

[DllImport("user32.dll")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool ShowWindow(IntPtr hWnd, ShowWindowEnum flags);

My code works well when the app is minimized in the task bar but it doesn't work when it is in the system tray (minimized+collapsped).

The Microsoft Docs seems to say that the enum item "ShowRestor" changes the visibility and activate the window so it should work. Is there something I did wrong ? Or this way doesn't work for the Wpf app ?

Elsassmania
  • 145
  • 2
  • 16
  • 1
    Instead of manually operating another process consider to simply send a signal to it (using [IPC](https://stackoverflow.com/q/953853/1997232)) so it will restore itself. – Sinatr Aug 18 '20 at 09:36
  • Is there no another way to do it ? It seems a bit overkill to add IPC in the app just to restore a collapsed windows – Elsassmania Aug 19 '20 at 06:54
  • I had exactly this problem and i used `NamedPipeClientStream` and `NamedPipeServerStream`. – rufw91 Aug 19 '20 at 12:30
  • @Elsassmania how do you solved the issue? – cpiock Apr 08 '22 at 13:19

1 Answers1

0

I had exactly this problem and i used NamedPipeClientStream and NamedPipeServerStream in .NET Core. In .NET, use this library: https://github.com/taylorjonl/SingleInstanceApp and have your MainWindow implement ISingleInstance inteface with the SignalExternalCommandLineArgs method as below:

 public bool SignalExternalCommandLineArgs(IList<string> args)
        {
            if (this.MainWindow == null)
                return true;
            if (this.MainWindow.WindowState == WindowState.Minimized)
                this.MainWindow.WindowState = WindowState.Normal;
            this.MainWindow.Activate();

            return true;
        }
rufw91
  • 157
  • 2
  • 8