C# List running applications which have a GUI - c#

How could I list all running applications which have a GUI in C#? I am trying to make some sort of a taskbar, so I have to know what processes are running. I can't list all processes of course, because that would be a total disaster. My idea is to only list processes with a gui, because that seems like what's happening in the "stock" taskbar.

You can list all processes that have a main window:
static IEnumerable<Process> WindowProcesses()
{
foreach(var proc in Process.GetProcesses())
{
if(proc.MainWindowHandle != IntPtr.Zero)
{
yield return proc;
}
}
}
This will enumerate all processes that have a main window, but may not necessarily list all processes that have any visible windows (e.g. services). For that, you need to P/Invoke EnumWindows and GetWindowThreadProcessId.

This code will fill a dropdown and set get it on foreground by selection, you can do it like this
[DllImport("User32.dll")]
static extern bool ShowWindow(IntPtr hWnd, uint nCmdShow);
[DllImport("User32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
private void ListTask()
{
Process[] processes = Process.GetProcesses();
foreach (Process process in Process.GetProcesses().
Where(p => !string.IsNullOrEmpty(p.MainWindowTitle)).ToList())
listBox1.Items.Add(process.ProcessName);
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
Process p = new Process();
string name = listBox1.SelectedItem.ToString();
p = Process.GetProcessesByName(name)[0];
const uint SWP_SHOWWINDOW = 0x0001;
ShowWindow(p.MainWindowHandle, SWP_SHOWWINDOW);
SetForegroundWindow(p.MainWindowHandle);
p.Dispose();
}

Related

wpf how to get program focus form windows

i made program it work in background, i want this program only work on program i select it
example : i created Auto clicker and i want to use this program just in games if the user go to any other program it doesn't work
this way i hope it is there
if(Windows.Focus.NameProgram.ToString() == "Call of Duty Cold War")
{
// here all commands i will put it later.
}
here i mean what windows focus it now if it is Call of Duty Cold War then work, if not dont work (of course still running in the background)
Use a function called GetForegroundWindow from Windows API.
The implementation further down gets the current focused window.
Documentation: GetForegroundWindow | MS Docs
public class GetFocusedWindow
{
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
private static string GetActiveWindowTitle()
{
const int nChars = 256;
StringBuilder Buff = new StringBuilder(nChars);
IntPtr handle = GetForegroundWindow();
if (GetWindowText(handle, Buff, nChars) > 0)
{
return Buff.ToString();
}
return null;
}
static void Main(string[] args)
{
while (true)
{
Thread.Sleep(2000);
Console.WriteLine(GetActiveWindowTitle());
}
}
}

Is it possible to use SendKeys for a specific application without SetForegroundWindow?

While working on the main screen, I want to send a right click command to Firefox, which is opened on the second vertical screen. But I don't want Firefox to become active when I send commands. I tried this but it didn't work:
const uint WM_KEYDOWN = 0x0100;
[DllImport("user32.dll")]
static extern bool PostMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);
private void button1_Click(object sender, EventArgs e)
{
var processes = Process.GetProcessesByName("firefox");
foreach (var proc in processes)
{
PostMessage(proc.MainWindowHandle, WM_KEYDOWN, (int)Keys.Right, 0);
// I have to use SendKeys.SendWait for the messages to be processed.
SendKeys.SendWait("{RIGHT}");
}
}
And this works, but every time I send a command, Firefox becomes active. It doesn't work when I disable the SetForegroundWindow method.
[DllImport("User32.dll")]
private static extern int SetForegroundWindow(IntPtr ptr);
private void button1_Click(object sender, EventArgs e)
{
var p = Process.GetProcessesByName("firefox").FirstOrDefault();
if (p != null)
{
IntPtr h = p.MainWindowHandle;
SetForegroundWindow(h);
SendKeys.SendWait("{RIGHT}");
}
}
A Click is a WM_KEYDOWN and WM_KEYUP. Can you try calling the functions using the first method like so
foreach (var proc in processes)
{
PostMessage(proc.MainWindowHandle, WM_KEYDOWN, (int)Keys.RButton, (IntPtr)0x001E0001);
PostMessage(proc.MainWindowHandle, WM_KEYUP, (int)Keys.RButton, (IntPtr)0xC01E0001);
// I have to use SendKeys.SendWait for the messages to be processed.
SendKeys.SendWait("{RIGHT}"); //I dont believe you need this with the above approach
}
You can also try sending the WM_CONTEXTMENU message if that is what you are after
I must also point out that Keys.Right is for the Right arrow key and not the right mouse click, you should use Keys.RButton instead
Here is the List of KeyCodes and more info on KeyStrokes in win32

How to put background window/process on top

I want to create a software like a virtualkeyboard, you have a AlwaysTop Window and use this to put some data on another process/windows. In this case I will record all data on clipboard and compare if this data is compatible with a pattern (A### is the patern and A123 is compatible with the patern), if yes the application will put it in a listbox and the user can paste it on another process/windows (already open) clicking on item on list.
My question is about how to put this information on the last application/process used, I already started a prototype of code but the line indicated is wrong, on my code it's the currentprocess and need to be the last used before click on my form.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
[DllImport("user32.dll")]
static extern IntPtr SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]
internal static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
[DllImport("User32.dll")]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
private void button2_Click(object sender, EventArgs e)
{
Process currentProcess = Process.GetCurrentProcess(); //this line is wrong
IntPtr hWnd = currentProcess.MainWindowHandle; //this line is wrong
if (hWnd != IntPtr.Zero)
{
SetForegroundWindow(hWnd);
ShowWindow(hWnd, 9);
SendKeys.Send("A123");
}
}
}
}
I get on simple solution, instead of get the process I just send the combination ALT+TAB and work for all cases that I need. Below the solution if anyone need in the future:
string old_clipboard = Clipboard.GetText();
Clipboard.SetText("A123");
SendKeys.SendWait("%{Tab}");
SendKeys.SendWait("^V");
Thread.Sleep(100);
Clipboard.SetText(old_clipboard);
Ps.: I put one delay because the SendWait works only on caller windows, as the target of ^V is another process it´s don´t work well.
Best regards. =)

how to detect a new application being launched from C#?

I have a .dll library for c# that loves to pop out a 'Welcome' screen when it starts.
This screen appears as an application in the task manager.
Is there some way to automatically detect this application/form being launched and close it?
Thanks! :)
Here us simple console application that will monitor and close specified window
class Program
{
static void Main(string[] args)
{
while(true)
{
FindAndKill("Welcome");
Thread.Sleep(1000);
}
}
private static void FindAndKill(string caption)
{
Process[] processes = Process.GetProcesses();
foreach (Process p in processes)
{
IntPtr pFoundWindow = p.MainWindowHandle;
StringBuilder windowText = new StringBuilder(256);
GetWindowText(pFoundWindow, windowText, windowText.Capacity);
if (windowText.ToString() == caption)
{
p.CloseMainWindow();
Console.WriteLine("Excellent kill !!!");
}
}
}
[DllImport("user32.dll", EntryPoint = "GetWindowText",ExactSpelling = false, CharSet = CharSet.Auto, SetLastError = true)]
private static extern int GetWindowText(IntPtr hWnd,StringBuilder lpWindowText, int nMaxCount);
}
If it's running within your process and opening a Form (not a Dialog), you can use something like this to close all Forms which aren't opened by your own Assembly.
foreach (Form form in Application.OpenForms)
if (form.GetType().Assembly != typeof(Program).Assembly)
form.Close();
What is your own Assembly is defined by the class Program, you could also use Assembly.GetExecutingAssembly or Assembly.GetCallingAssembly, but I'm not sure it will behave correctly, if you run the Application inside Visual Studio (since it might return the VS Assembly).

Maintaining focus on a form

I am developing a software for a blind individual in C# .NET.
The software works only with the keyboard and voice to speech.
When the computer starts the program is in the start up menu, but for some reason the program is activated not in focus therefore it does not work properly unless the focus is re transferred to it.
I found a way to hook keyboard keys even when the software is not in focus but I don't see that as a solution.
I want a way to do one or more of the following:
Make sure the program loads on start up and is in focus.
Maintain focus on the program (this computer will be run only using this program).
Find a keyboard shortcut, preferably one key only (not Alt + Tab) to return focus to the program.
There are many ways you can solve this ie you can run on startup console app that will run and focus your program:
[STAThread]
static void Main(string[] args)
{
System.Diagnostics.Process myProcess = new System.Diagnostics.Process();
myProcess.StartInfo.FileName = "calc";
myProcess.Start();
IntPtr hWnd = myProcess.Handle;
SetFocus(new HandleRef(null, hWnd));
}
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern IntPtr SetFocus(HandleRef hWnd);
You can host a windows service application and using timer check if your app is alive and is focused or you can use hotkeys to bring it back focused: http://www.codeproject.com/KB/miscctrl/ashsimplehotkeys.aspx
Edited
this is console application, that will keep your app alive and focused (tested). i need to find walkaround for windows service becouse since vista something changed and form is invisible when stared from service :P
static Process myProcess;
[STAThread]
static void Main(string[] args)
{
for (int i = 0; i < 10000; i++)
{
//count how many procesess with this name are active if more than zero its still alive
Process[] proc = Process.GetProcessesByName("myprog");
if (proc.Length > 0)
{
//its alive check if it has focus
if (proc[0].MainWindowHandle != GetForegroundWindow())
{
SetFocus(proc[0].MainWindowHandle);
}
}
//no process start new one and focus on it
else
{
myProcess = new Process();
myProcess.StartInfo.FileName = "C:\\aa\\myprog.exe";
myProcess.Start();
SetFocus(myProcess.Handle);
}
Thread.Sleep(1000);
}
}
private static void SetFocus(IntPtr handle)
{
SwitchToThisWindow(handle, true);
}
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll", SetLastError = true)]
public static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab);

Categories