C#试图枚举每个进程线程的每个窗口
问题描述:
我想做一个小应用程序来枚举每个进程线程中的每个窗口名称在控制台中。C#试图枚举每个进程线程的每个窗口
我目前使用的代码可以在Windows 7机器上正常工作,但由于某种原因,它在没有任何堆栈跟踪或错误消息的情况下在Windows 10中查找,我试图添加几乎所有内部的try-catch,但我didn我也没有收到任何消息,所以我迷路了。
下面是代码:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
namespace ConsoleApplication3
{
class Program
{
private delegate bool EnumThreadDelegate(IntPtr hWnd, IntPtr lParam);
[DllImport("user32.dll")]
private static extern bool EnumThreadWindows(int dwThreadId, EnumThreadDelegate lpfn, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, int wParam, StringBuilder lParam);
static void Main(string[] args)
{
Process[] processes = Process.GetProcesses();
Console.WriteLine("Detected: " + processes.Length + " processes.");
foreach (Process process in processes)
{
IEnumerable<IntPtr> windowHandles = null;
try
{
windowHandles = EnumerateProcessWindowHandles(process);
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace);
continue;
}
Console.WriteLine("Checking process" + process.ProcessName);
foreach (var handle in windowHandles)
{
StringBuilder message = new StringBuilder();
try
{
SendMessage(handle, 0x000D, message.Capacity, message);
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace);
continue;
}
if (message.Length == 0)
{
continue;
}
Console.WriteLine("Window name: " + message.ToString());
}
}
Console.WriteLine("Finished!");
Console.ReadLine();
}
private static IEnumerable<IntPtr> EnumerateProcessWindowHandles(Process process)
{
List<IntPtr> handles = new List<IntPtr>();
ProcessThreadCollection threads = null;
try
{
threads = process.Threads;
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace);
return handles;
}
foreach (ProcessThread thread in threads)
{
try
{
EnumThreadWindows(thread.Id, (hWnd, lParam) => { handles.Add(hWnd); return true; }, IntPtr.Zero);
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace);
continue;
}
}
return handles;
}
}
}
为什么它可能卡住任何想法?
UPDATE
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
namespace ConsoleApplication3
{
class Program
{
private delegate bool EnumThreadDelegate(IntPtr hWnd, IntPtr lParam);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool EnumThreadWindows(int dwThreadId, EnumThreadDelegate lpfn, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, int wParam, StringBuilder lParam);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool IsWindowVisible(IntPtr handle);
static void Main(string[] args)
{
Process[] processes = Process.GetProcesses();
Console.WriteLine("Detected: " + processes.Length + " processes.");
foreach (Process process in processes)
{
IEnumerable<IntPtr> windowHandles = null;
try
{
windowHandles = EnumerateProcessWindowHandles(process);
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace);
continue;
}
Console.WriteLine("Checking process: " + process.ProcessName);
foreach (IntPtr handle in windowHandles)
{
if (handle == null)
{
continue;
}
if (!IsWindowVisible(handle))
{
continue;
}
StringBuilder message = new StringBuilder();
int capacity = 0;
try
{
capacity = message.Capacity;
}
catch(Exception e)
{
Console.WriteLine(e.StackTrace);
continue;
}
try
{
SendMessage(handle, 0x000D, capacity, message);
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace);
continue;
}
if (message.Length == 0)
{
continue;
}
Console.WriteLine("Window name: " + message.ToString());
}
}
Console.WriteLine("Finished!");
Console.ReadLine();
}
private static IEnumerable<IntPtr> EnumerateProcessWindowHandles(Process process)
{
List<IntPtr> handles = new List<IntPtr>();
ProcessThreadCollection threads = null;
try
{
threads = process.Threads;
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace);
return handles;
}
foreach (ProcessThread thread in threads)
{
if (thread == null)
{
continue;
}
int threadId = 0;
try
{
threadId = thread.Id;
}
catch(Exception e)
{
Console.WriteLine(e.StackTrace);
continue;
}
try
{
EnumThreadWindows(threadId, (hWnd, lParam) => { handles.Add(hWnd); return true; }, IntPtr.Zero);
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace);
continue;
}
}
return handles;
}
}
}
谢谢大家。
答
尝试运行控制台应用程序管理员,如果问题仍然出现,我建议使用API GetLastError
这就是它的作用:
检索调用线程的最后一个错误代码值。最后的错误代码以每个线程为基础进行维护。多线程不会覆盖彼此的最后一个错误代码。
要读出值知道的问题,尝试如何使用它此链接为指导做好: https://msdn.microsoft.com/en-us/library/windows/desktop/ms679360(v=vs.85).aspx
+0
感谢您的回答,我试过这个,但我没有得到任何输出。 –
我相信这与了Windows 10应用程序沙箱和应用程序,但我做的不确定。我知道我们无法深入了解我们使用的方式,但我不知道这样做的正确方法。 Windows 10使用了很多虚拟环境来托管应用程序,所以我只是在这里猜测......请不要将此作为任何答案。 –
感谢您的回答迈克尔Pucket II,我试着在另一台机器与Windows 10和工作正常,但看起来像代码随机失败也在Windows 7没有任何消息/痕迹/错误...我真的不知道在哪里开始解决我的问题。 –
我有一个想法。你的windowHandles = null已经。 EnumerateProcessWindowHandles(进程)不会失败,但仍然返回null。然后当你输入foreach(var handle在windowHandles中)它会崩溃。你应该得到一个错误,但如果这是部署你可能不会。我将windowHandles设置为一个空的枚举,以便foreach循环至少有一个零计数值,并且永远不会有空值。这是我能够立即注意到的唯一缺陷,如果是我,就必须从那里开始。 –