-1

I have a windows form application that opens another vendor's application. If the vendor's application is not running, my code opens it and it becomes visible as expected. However, if the vendor's application is already running minimized or in the system tray, I can't make it visible when I call Process.Start(). Is there a way to make a currently running application visible/shown whether if it is minimized or in the system tray?

This is my code to open the other application which only works if the VendorProgram.exe is not running. If VendorProgram.exe is running but minimized it doesn't make it visible/shown, which is what I need.

ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.CreateNoWindow = false;
startInfo.UseShellExecute = false;
startInfo.FileName = "C:\\Program Files (x86)\\VendorProgram.exe";
startInfo.WindowStyle = ProcessWindowStyle.Normal;


Process p = Process.Start(startInfo);

EDIT: In case it isn't clear, I am not trying to make an application open itself, I am trying to open a separate vendor's application from my application.

4
  • 1
    Please read this carefully stackoverflow.com/questions/19147/…
    – Steve
    Commented Sep 28, 2015 at 19:32
  • There's no standard way of making an external application "show itself" when it's in the Tray (not the TaskBar)...
    – Idle_Mind
    Commented Sep 28, 2015 at 21:34
  • 1
    @Idle_Mind By "no standard way" do you mean it's not possible from .net/c#?
    – Heinrich
    Commented Sep 28, 2015 at 22:57
  • No...in Windows itself, there is no easy or foolproof method to "restore" an application from the tray. The window/form that is displayed when you use a Tray Icon may or may not be the same form that appeared when the application was initially launched; the app may make a new instance of the form. In other words, the main form and the tray icon are not necessarily bound to each other. As far as I know, there is also no windows message you can send to a tray icon to make it "restore" either...
    – Idle_Mind
    Commented Sep 29, 2015 at 4:12

3 Answers 3

2

First of all, you are somewhat trying to reinvent the wheel. As Steve pointed out in the comments, there are already built-in methods for achieving a single-instance application, such as with a Mutex.

The "show it when it is minimized to the tray" part is the tricky one, however.

You could loop over running processes to find yours, and then optionally start a new one, or call up the already running one. This requires a little p/invoke magic:

[DllImport("user32.dll")]
private static extern IntPtr FindWindow(String lpClassName, String lpWindowName);
[DllImport("user32.dll")]
private static extern Boolean SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern Boolean ShowWindow(IntPtr hWnd, Int32 nCmdShow);

var bFound = false;
foreach (var proc in Process.GetProcesses())
{
    if (proc.ProcessName.Equals("YourProcessName"))
    {
        var window = FindWindow(null, proc.MainWindowTitle);
        if (!window.Equals(IntPtr.Zero))
        {
            //Mixed results...this might be redundant
            SetForegroundWindow(window);
            ShowWindow(window, 1);  //SW_NORMAL
            bFound =true;
        }
    }
}

if (!bFound)
{
    var startInfo = new ProcessStartInfo();
    startInfo.CreateNoWindow = false;
    startInfo.UseShellExecute = false;
    startInfo.FileName = "C:\\Program Files (x86)\\Program.exe";
    startInfo.WindowStyle = ProcessWindowStyle.Normal;
    Process.Start(startInfo);
}
3
  • 1
    I'm just trying to open the gui of a running application from c# not reinvent the wheel. Your example looked promising but it didn't open the form of the running process whether it was minimized or in the system tray. SetForeground and ShowWindow didn't do anything.
    – Heinrich
    Commented Sep 28, 2015 at 20:19
  • You could try not using the window variable, and replacing its usages with proc.MainWindowHandle instead. FindWindow will find the first match, perhaps it returned the wrong handle. Commented Sep 28, 2015 at 20:44
  • 2
    MainWindowHandle didn't do it either.
    – Heinrich
    Commented Sep 28, 2015 at 22:49
2

I found this and it helped me do what I needed.

The trick was to use the correct window name in FindWindow() not process.MainWindowTitle. Apparently, process.MainWindowTitle brings back the first window created by the application. That might work sometimes but not always. I needed to put the name of the actual window that was minimized in the system tray. Using notepad for example, if the title was my file - Notepad, that's what you need to put in FindWindow. This seems clumsy but works everytime for me. Notepad isn't the application I'm opening but it's for example.

This doesn't work

foreach (var proc in Process.GetProcesses()) {
    if (proc.ProcessName.Equals("Notepad"))
    {
      IntPtr window = FindWindow(null, proc.MainWindowTitle);    
      ShowWindow(hWnd, 1);
      break;
    }
 }

this does

  IntPtr window = FindWindow(null, "my file - Notepad");   
  ShowWindow(hWnd, 1); 
1

did you try using

[DllImport("user32.dll")]
private static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);

instead of "ShowWindow(IntPtr hWnd, int nCmdShow)"?

Not the answer you're looking for? Browse other questions tagged or ask your own question.