9

我正在尝试获取所有打开的应用程序的列表。具体来说,如果您打开任务管理器并转到应用程序选项卡,该列表。

我试过使用这样的东西:

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
    {
    }
}

就像我发现的几个例子一样,但这并没有为我拉出所有的应用程序。它只抓取了我在任务管理器中可以看到的或者我知道我已经打开的大约一半。例如,由于某种原因,此方法不支持 Notepad++ 或 Skype,但支持谷歌浏览器、计算器和 Microsoft Word。

有谁知道为什么这不能正常工作或如何这样做?

另外,一位朋友建议这可能是权限问题,但我以管理员身份运行 Visual Studio,并且它没有改变。

编辑:我遇到的问题是,我得到的大多数解决方案只是返回一个所有进程的列表,这不是我想要的。我只想要打开的应用程序或窗口,例如任务管理器上显示的列表。不是每个进程的列表。

另外,我知道这里有错误的代码,包括空的 catch 块。这是一个一次性项目,只是为了首先弄清楚它是如何工作的。

4

5 回答 5

12

这里的代码示例似乎给出了您的要求。修改版:

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;
    }
}

使用上面的代码,调用User32Helper.GetDesktopWindows()应该给你一个包含所有打开的应用程序的句柄/标题的列表,以及它们是否可见。请注意,true无论窗口的可见性如何,都会返回,因为该项目仍会按照作者的要求显示在任务管理器的应用程序列表中。

然后,您可以使用集合中某个项目的相应 Handle 属性来使用其他窗口函数(例如ShowWindowEndTask)执行许多其他任务。

于 2014-05-27T12:49:37.907 回答
2

正如马修指出的那样,这可能是因为它们没有主要标题,因此您将它们过滤掉了。下面的代码让所有进程运行。然后,您可以使用它Process.ProcessName来过滤掉您不想要的那个。是有关使用 ProcessName 的文档。

using System.Diagnostics;

Process[] processes = Process.GetProcesses();

foreach (Process process in processes)
{
   //Get whatever attribute for process
}
于 2013-01-08T02:57:56.723 回答
0

我认为,出于某种原因,某些进程的 MainWindowTitle 为空,因此您正在跳过这些进程。试试这个只是为了测试:

foreach (var p in Process.GetProcesses())
{
     sb.Append("\r\n");
     sb.Append("Process Name: " + p.ProcessName);
     sb.Append("\r\n");
}

如果你的 try...catch 出现错误,可能会跳过一些进程,所以也可以尝试不使用它。

更新: 试试这个,它很难看,并采取一些没有窗口的进程,但也许你可以过滤..

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);
    }
}
于 2013-01-08T03:02:48.847 回答
0

你可以试试像这样的克里斯

//下面的更新将为您提供在应用程序选项卡中运行的所有进程

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("");
    }
}
于 2013-01-08T02:58:27.440 回答
0

正如其他人所说,这是因为某些应用程序(Notepad++ 就是其中之一)没有 MainWindowTitle,为了解决这个问题,我的代码(例如)如下所示:

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);
    }
}
于 2013-01-08T02:59:20.350 回答