Reputation: 4107
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
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