Reputation: 109
I'm trying to get the list of all the open applications. Specifically, if you open the task manager and go to the applications tab, that list.
I've tried using something like this:
foreach (var p in Process.GetProcesses())
{
try
{
if (!String.IsNullOrEmpty(p.MainWindowTitle))
{
sb.Append("\r\n");
sb.Append("Window title: " + p.MainWindowTitle.ToString());
sb.Append("\r\n");
}
}
catch
{
}
}
Like in a few examples I've found, but this doesn't pull all the applications for me. It's only grabbing about half the ones I can see in the task manager or that I know I have open. For example, this method doesn't pick up Notepad++ or Skype for some reason, but DOES pick up Google Chrome, Calculator, and Microsoft Word.
Does anyone know either why this isn't working correctly or how to do so?
Also, a friend suggested it might be a permissions issue, but I am running visual studio as administrator and it hasn't changed.
EDIT: The problem I'm getting is that most of the solutions I've been given just returns a list of ALL processes, which isn't what I want. I just want the open applications or windows, like the list that appears on the task manager. Not a list of every single process.
Also, I know there is bad code in here, including the empty catch block. This was a throwaway project just to figure out how this works in the first place.
Upvotes: 10
Views: 19696
Reputation: 2191
The code example here appears to give what you're asking for. Modified version:
public class DesktopWindow
{
public IntPtr Handle { get; set; }
public string Title { get; set; }
public bool IsVisible { get; set; }
}
public class User32Helper
{
public delegate bool EnumDelegate(IntPtr hWnd, int lParam);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool IsWindowVisible(IntPtr hWnd);
[DllImport("user32.dll", EntryPoint = "GetWindowText",
ExactSpelling = false, CharSet = CharSet.Auto, SetLastError = true)]
public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpWindowText, int nMaxCount);
[DllImport("user32.dll", EntryPoint = "EnumDesktopWindows",
ExactSpelling = false, CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool EnumDesktopWindows(IntPtr hDesktop, EnumDelegate lpEnumCallbackFunction,
IntPtr lParam);
public static List<DesktopWindow> GetDesktopWindows()
{
var collection = new List<DesktopWindow>();
EnumDelegate filter = delegate(IntPtr hWnd, int lParam)
{
var result = new StringBuilder(255);
GetWindowText(hWnd, result, result.Capacity + 1);
string title = result.ToString();
var isVisible = !string.IsNullOrEmpty(title) && IsWindowVisible(hWnd);
collection.Add(new DesktopWindow { Handle = hWnd, Title = title, IsVisible = isVisible });
return true;
};
EnumDesktopWindows(IntPtr.Zero, filter, IntPtr.Zero);
return collection;
}
}
With the above code, calling User32Helper.GetDesktopWindows()
should give you a list of containing the Handle/Title for all open applications as well as whether or not they're visible. Note that true
is returned regardless of the window's visibility, as the item would still show up in the Applications list of Task Manager as the author was asking.
You could then use the corresponding Handle property from one of the items in the collection to do a number of other tasks using other Window Functions (such as ShowWindow or EndTask).
Upvotes: 13
Reputation: 18863
You can try something like this Chris
//UPDATED below will get you all the processes running in the Application Tab
Process[] myProcesses = Process.GetProcesses();
foreach (Process P in myProcesses)
{
if (P.MainWindowTitle.Length > 1)
{
Console.WriteLine(P.ProcessName + ".exe");
Console.WriteLine(" " + P.MainWindowTitle);
Console.WriteLine("");
}
}
Upvotes: 0
Reputation: 536
As others have said it's because some applications (Notepad++ being one) don't have a MainWindowTitle, to counter this my code (as an example) looks like this:
Process[] processes = Process.GetProcesses();
foreach (Process pro in processes)
{
if (pro.MainWindowTitle != "")
{
listBox.Items.Add(pro.ProcessName + " - " + pro.MainWindowTitle);
}
else
{
listBox.Items.Add(pro.ProcessName);
}
}
Upvotes: 0
Reputation: 2118
I think that, for some reason, MainWindowTitle is null for some processes, so you are skipping those ones. Try this just for test:
foreach (var p in Process.GetProcesses())
{
sb.Append("\r\n");
sb.Append("Process Name: " + p.ProcessName);
sb.Append("\r\n");
}
Maybe your try...catch is jumping some processes if it gets some error, so try without it also.
UPDATE: Try this, it's ugly and take some processes that has no windows but maybe you can filter..
var proc = new Process()
{
StartInfo = new ProcessStartInfo
{
FileName = "tasklist",
Arguments = "/V",
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
}
};
proc.Start();
StreamReader sr = proc.StandardOutput;
while (!sr.EndOfStream)
{
string line = sr.ReadLine();
Match m = Regex.Match(line, @".{52}(\d+).{94}(.+)$");//157
if (m.Success)
{
int session = Convert.ToInt32(m.Groups[1].Value);
string title = m.Groups[2].Value.Trim();
if (session == 1 && title != "N/A") sb.AppendLine(title);
}
}
Upvotes: 0
Reputation: 3258
As Mathew noted its probably because they don't have main titles and thus your filtering them out. The below code gets all the processes running. You could then use Process.ProcessName
to filter out the one you don't want. Here is the documentation on using ProcessName.
using System.Diagnostics;
Process[] processes = Process.GetProcesses();
foreach (Process process in processes)
{
//Get whatever attribute for process
}
Upvotes: 1