7

I have built a C# Windows Form application. When the form loads, it's full screen. The form has icons on it that launch other applications (not forms). I'm trying to accomplish determining whether the application is already running or not and if it's not, start it, otherwise bring it to the front. I have accomplished determining whether the application is running or not and if it's not, to start it, I just can't figure out how to bring it to the front if it is. I have read other results on Google and Stack Overflow, but haven't been able to get them to work.

Any help is greatly appreciated!

My code, so far, is:

private void button4_Click(object sender, EventArgs e)
{
    Process[] processName = Process.GetProcessesByName("ProgramName");
    if (processName.Length == 0)
    {
        //Start application here
        Process.Start("C:\\bin\\ProgramName.exe");
    }
    else
    {
        //Set foreground window
        ?
    }
}
Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
scedsh8919
  • 131
  • 1
  • 1
  • 10
  • Take a look at https://stackoverflow.com/questions/2636721/bring-another-processes-window-to-foreground-when-it-has-showintaskbar-false#2636915 ... It should work - regardless of the showintaskbar part. – Aaron Apr 13 '18 at 17:33
  • Possible duplicate of [Bring another processes Window to foreground when it has ShowInTaskbar = false](https://stackoverflow.com/questions/2636721/bring-another-processes-window-to-foreground-when-it-has-showintaskbar-false) – Andrew Drake Apr 13 '18 at 17:34
  • Possible duplicate of [Dynamically set focus to another program in C#](https://stackoverflow.com/questions/39262517/dynamically-set-focus-to-another-program-in-c-sharp) – Ben Apr 13 '18 at 17:34
  • Process.Start() returns a Process object. Don't lose it. You need its Exited event to know that it terminated. And you'll probably like its MainWindowHandle property. – Hans Passant Apr 13 '18 at 17:47
  • I feel like this is a good code to use, but I'm failing to understand where to input the specifics about the program it should search for. https://stackoverflow.com/a/37724335/6490340 – scedsh8919 Apr 13 '18 at 18:27

2 Answers2

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

private IntPtr handle;

private void button4_Click(object sender, EventArgs e)
{
    Process[] processName = Process.GetProcessesByName("ProgramName");
    if (processName.Length == 0)
    {
        //Start application here
        Process.Start("C:\\bin\\ProgramName.exe");
    }
    else
    {
        //Set foreground window
        handle = processName[0].MainWindowHandle;
        SetForegroundWindow(handle);
    }
}

If you also wish to show the window even if it is minimized, use:

if (IsIconic(handle))
    ShowWindow(handle, SW_RESTORE);
Andrew Drake
  • 655
  • 1
  • 11
  • 25
  • How would the above code integrate with my code shown? When I try to add it, it's getting stuck on the second line "handle =" saying that "handle" doesn't exist in the current context. – scedsh8919 Apr 13 '18 at 18:26
  • Apologies, you could either move "private IntPtr handle;" outside of the method, or you could remove "private" all-together. I will edit the post to reflect the former. I just realized your processName is also an array, so I will reflect that as well. – Andrew Drake Apr 13 '18 at 18:35
13

Although several answers here are marked as working, they did not work in my case. I found correct code, which worked for me on blog of Joseph Gozlan. I'm repeating here this awesome code for convenience. Notice slight but very important difference with async call, compared to other answers. All credits to original code author.

[DllImport("user32.dll")]
public static extern bool ShowWindowAsync(HandleRef hWnd, int nCmdShow);
[DllImport("user32.dll")]
public static extern bool SetForegroundWindow(IntPtr WindowHandle);
public const int SW_RESTORE = 9;
    
private void FocusProcess(string procName)
{
  Process[] objProcesses = System.Diagnostics.Process.GetProcessesByName(procName); 
  if (objProcesses.Length > 0)
  {
    IntPtr hWnd = IntPtr.Zero;
    hWnd = objProcesses[0].MainWindowHandle;
    ShowWindowAsync(new HandleRef(null,hWnd), SW_RESTORE);
    SetForegroundWindow(objProcesses[0].MainWindowHandle);
  }
}
Atiris
  • 2,613
  • 2
  • 28
  • 42
Boris Zinchenko
  • 2,142
  • 1
  • 24
  • 34
  • Worked perfectly, and just a quick example calling that function would be useful, I used it like this: FocusProcess(System.Diagnostics.Process.GetCurrentProcess().ProcessName) – jas May 20 '21 at 19:13
  • This works well. You've already assigned hWnd so it can be passed to SetForegroundWindow at the end rather than objProcesses[0].MainWindowHandle. – Julian Melville Oct 28 '21 at 01:41