2

Below is my code. Here you can see that i am using constant for hide/show the window. Hide the other application from the another application in C#.net.

    private const int SW_HIDE = 0;
    private const int SW_SHOW = 5;

    [DllImport("User32")]
    private static extern int ShowWindow(int hwnd, int nCmdShow);

    private void btnHide_Click(object sender, EventArgs e){

        Process[] processRunning = Process.GetProcesses();
        foreach (Process pr in processRunning){

            if (pr.ProcessName == FileName){
                hWnd = pr.MainWindowHandle.ToInt32();
                ShowWindow(hWnd, SW_HIDE);
            }
        }
    }

    private void btnShow_Click(object sender, EventArgs e){

        Process[] processRunning = Process.GetProcesses();

        foreach (Process pr in processRunning){
            if (pr.ProcessName == FileName){

                hWnd = pr.MainWindowHandle.ToInt32();
                ShowWindow(hWnd, SW_SHOW);
            }
        }
    }
5

2 Answers 2

2

When visible the MainWindowHandle is non-zero, after the Window is hidden the handle gets set to 0. I haven't found a way yet to get the required handle - maybe a work around would be to maintain a list of the windows you have hidden.

List<int> HiddenWindows = new List<int>();

private void btnHide_Click(object sender, RoutedEventArgs e)
{
  Process[] processRunning = Process.GetProcessesByName(FileName);
  foreach (Process pr in processRunning)
  {
    int hWnd = pr.MainWindowHandle.ToInt32();
    if (hWnd == 0)
      continue;
    ShowWindow(hWnd, SW_HIDE);
    HiddenWindows.Add(hWnd);
  }
}

private void btnShow_Click(object sender, RoutedEventArgs e)
{
  foreach (int hWnd in HiddenWindows)
  {
    ShowWindow(hWnd, SW_SHOW);
  }
  HiddenWindows.Clear();
}

NOTE - rather than iterate through all processes returned by GetProcesses - you can use GetProcessesByName just to get the processes you are interested in.

There is an answer here based on other User32 functions - but seems quite complex : Unhide process by its process name?

A quick test with a WPF application showed multiple Window handles found using the code in the linked solution - the answer is to remove the return after the call to ShowWindow. I have added a modified version below to reopen multiple application instances if required.

private const int SW_SHOW = 5;
private String FileName = "notepad";

[DllImport("User32")]
private static extern int ShowWindow(IntPtr hwnd, int nCmdShow);
[DllImport("User32.dll")]
private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string strClassName, string strWindowName);

[DllImport("user32.dll")]
private static extern int GetWindowThreadProcessId(IntPtr hWnd, out int ProcessId);

private void btnShow2_Click(object sender, RoutedEventArgs e)
{
  //an array of all processes with name "processName"
  Process[] localAll = Process.GetProcessesByName(FileName);

  foreach (var pr in localAll)
  {
    IntPtr hWnd = IntPtr.Zero;
    int prcsId = 0;

    //check all open windows (not only the process we are looking) begining from the
    //child of the desktop, handle = IntPtr.Zero initialy.
    do
    {
      //get child handle of window who's handle is "handle".
      hWnd = FindWindowEx(IntPtr.Zero, hWnd, null, null);
      GetWindowThreadProcessId(hWnd, out prcsId); //get ProcessId from "handle"

      //if it matches what we are looking
      //Note there maybe multiple Windows found - so try all of them
      if (prcsId == pr.Id)
        ShowWindow(hWnd, SW_SHOW); //Show Window
    } while (hWnd != IntPtr.Zero);
  }
}

NOTE that I have modified the ShowWindow definition to use an IntPtr as the type for the Window handle - this is the preferred type to use & it is the actual type of MainWindowHandle. In your hide method just change the code to be

IntPtr hWnd = pr.MainWindowHandle;

or the entire loop to

foreach (Process pr in processRunning)
{
  ShowWindow(pr.MainWindowHandle, SW_HIDE);
}
6
  • Thank you PaulF. You solution is correct. But in my scenario, i want to close the first application after hiding the another application. And again when i start my first application, i want to show the hidden application. Commented Mar 6, 2019 at 4:29
  • Unfortunately, once hidden the application has no window - so the applications MainWindowHandle is set to zero. The answer in the link I added should do the trick - getting the process ID & then a brute force search of all available windows to find the one attached to process matched by ID.
    – PaulF
    Commented Mar 6, 2019 at 11:53
  • i try as given in your link,it does not work also i try ShowWindow(handle, SW_RESTORE); // Restore Windows ShowWindow(handle, SW_SHOW); //Show Window SetForegroundWindow(handle); Commented Mar 6, 2019 at 14:06
  • @AnkitUpadhyay: I have updated with code that works for me based on the original link code.
    – PaulF
    Commented Mar 6, 2019 at 14:41
  • I try on Notepad, that working good, My problem is in some condition the application is start without UI. So without load UI how can i show the UI? Commented Mar 7, 2019 at 6:08
0

This is how Process.GetProcess() works.

Once you hide the main window of process its MainWindowHandle for next iteration over processes will become IntPtr.Zero. It has something to do with how MainWindowHandle is retrieved I guess.

Solutions:

  1. enumerate processes once
  2. store hWnd (e.g. in Dictionary<string, int>) and call ShowWindow() without retrieving processes again.

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