Zsw
Zsw

Reputation: 4107

How to use ShowWindow to show already hidden windows?

I am writing a C# program where I use ShowWindow to show or hide the windows of other processes. My problem is that I am not able to use my program to show or hide windows of processes if the window was already hidden before the program is run.

For example, if I were to run my program, hide the window of some other process, then show it, it would work as normal. However, if I were to run my program, hide the window of some other process, terminate my program, then run my program again, I will not be able to show the window of that process anymore.

I would like to be able to show windows of hidden processes even if they were hidden before the program is ran. How may I achieve this?

Program.cs

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {

            if (args.Length == 2)
            {

                if (args[0] == "showh")
                {
                    int handle;
                    int.TryParse(args[1], out handle);
                    App.ShowHandle(handle);
                } 
                else 
                {
                    Process[] processes = Process.GetProcesses();

                    foreach (Process process in processes)
                    {

                        App app = new App(process);

                        if (args[1] == app.Name)
                        {
                            if (args[0] == "show")
                            {
                                app.Show();
                            }
                            else
                            {
                                app.Hide();
                            }
                        }
                    }


                }


            }
        }
    }
}

App.cs

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{


    public class App
    {

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

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

        public String Name { get; private set; }

        private Process process { get; set; }

        public App(Process process) 
        {
            this.Name = process.ProcessName;
            this.process = process;
        }

        public void Hide() 
        {
            int windowHandle = this.process.MainWindowHandle.ToInt32();
            Console.WriteLine("Hiding {0}: has window handle {1}", this.Name, windowHandle);
            ShowWindow(windowHandle, SW_HIDE);
        }

        public void Show()
        {
            int windowHandle = this.process.MainWindowHandle.ToInt32();
            Console.WriteLine("Showing {0}: has window handle {1}", this.Name, windowHandle);
            ShowWindow(windowHandle, SW_SHOW);

        }

        public static void ShowHandle(int handle)
        {
            Console.WriteLine("Showing window handle {0}", handle);
            ShowWindow(handle, SW_SHOW);
        }
    }
}

Update 1: added minimal and complete code example.

Update 2: After further experimentation, most processes do in fact give me a window handle of zero. However, in rare circumstances, I get a non-zero window handle, but the window handle is incorrect.

Incorrect as in: the handle value when the process is hidden is different from the handle value when I attempt to show the process.

However, if I remember the process' window handle when it is hidden, I can show the window again regardless. I have updated my code example to reflect that.

My question then becomes: Why am I unable to get the correct window handle of processes if the process was hidden to begin with? (But I am able to get the window handle if the process was visible, and then hidden.)

Upvotes: 0

Views: 8959

Answers (1)

Zsw
Zsw

Reputation: 4107

Since I have not received any answers, I came up with the following solution:

Remember the window handle of the process and associate it with the process ID. Save this to a file. When my application is restarted, read from the file. I can now use these saved window handles to show the hidden windows for the associated process ID.

And I can also use this id to get back the process object.

Process proc = Process.GetProcessById(processID);

Additionally, once the windows are shown, I am once again able to get the window handle with

int windowHandle = this.process.MainWindowHandle.ToInt32();

If anyone has a better solution please comment. However, this is the solution I am going with for now.

Upvotes: 1

Related Questions