我有兴趣开发一个开源密码管理器Keepass的插件。现在,Keepass目前根据窗口标题检测要为您复制/粘贴的密码。这可以防止Keepass检测到根据当前网站(例如Chrome)未主动更新其窗口标题的应用所需的当前密码。
如何浏览与Spy ++工作方式类似的其他进程窗口元素(按钮,标签,文本框)?当您运行Spy ++时,您可以将鼠标悬停在其他程序窗口上,并获取有关各种控件(标签,文本框等)的各种属性的各种信息。理想情况下,我希望我的Keepass插件通过遍历活动窗口的元素来增强当前窗口检测,以便找到匹配的帐户来复制/粘贴密码。
如何使用C#?
遍历其他进程窗口元素并能够检索标签和文本框值答案 0 :(得分:25)
我在这里回答类似的问题:How can I detect if a thread has windows handles?。就像它说的那样,主要的想法是使用EnumWindows和EnumChildWindows API调用来枚举进程窗口及其子窗口以获取窗口句柄,然后使用WM_GETTEXT调用GetWindowText或SendDlgItemMessage来获取窗口文本。我修改了代码来做一个应该做你需要的例子(对不起,它有点长:)。它遍历进程及其窗口并将窗口文本转储到控制台中。
static void Main(string[] args)
{
foreach (Process procesInfo in Process.GetProcesses())
{
Console.WriteLine("process {0} {1:x}", procesInfo.ProcessName, procesInfo.Id);
foreach (ProcessThread threadInfo in procesInfo.Threads)
{
// uncomment to dump thread handles
//Console.WriteLine("\tthread {0:x}", threadInfo.Id);
IntPtr[] windows = GetWindowHandlesForThread(threadInfo.Id);
if (windows != null && windows.Length > 0)
foreach (IntPtr hWnd in windows)
Console.WriteLine("\twindow {0:x} text:{1} caption:{2}",
hWnd.ToInt32(), GetText(hWnd), GetEditText(hWnd));
}
}
Console.ReadLine();
}
private static IntPtr[] GetWindowHandlesForThread(int threadHandle)
{
_results.Clear();
EnumWindows(WindowEnum, threadHandle);
return _results.ToArray();
}
// enum windows
private delegate int EnumWindowsProc(IntPtr hwnd, int lParam);
[DllImport("user32.Dll")]
private static extern int EnumWindows(EnumWindowsProc x, int y);
[DllImport("user32")]
private static extern bool EnumChildWindows(IntPtr window, EnumWindowsProc callback, int lParam);
[DllImport("user32.dll")]
public static extern int GetWindowThreadProcessId(IntPtr handle, out int processId);
private static List<IntPtr> _results = new List<IntPtr>();
private static int WindowEnum(IntPtr hWnd, int lParam)
{
int processID = 0;
int threadID = GetWindowThreadProcessId(hWnd, out processID);
if (threadID == lParam)
{
_results.Add(hWnd);
EnumChildWindows(hWnd, WindowEnum, threadID);
}
return 1;
}
// get window text
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern int GetWindowTextLength(IntPtr hWnd);
private static string GetText(IntPtr hWnd)
{
int length = GetWindowTextLength(hWnd);
StringBuilder sb = new StringBuilder(length + 1);
GetWindowText(hWnd, sb, sb.Capacity);
return sb.ToString();
}
// get richedit text
public const int GWL_ID = -12;
public const int WM_GETTEXT = 0x000D;
[DllImport("User32.dll")]
public static extern int GetWindowLong(IntPtr hWnd, int index);
[DllImport("User32.dll")]
public static extern IntPtr SendDlgItemMessage(IntPtr hWnd, int IDDlgItem, int uMsg, int nMaxCount, StringBuilder lpString);
[DllImport("User32.dll")]
public static extern IntPtr GetParent(IntPtr hWnd);
private static StringBuilder GetEditText(IntPtr hWnd)
{
Int32 dwID = GetWindowLong(hWnd, GWL_ID);
IntPtr hWndParent = GetParent(hWnd);
StringBuilder title = new StringBuilder(128);
SendDlgItemMessage(hWndParent, dwID, WM_GETTEXT, 128, title);
return title;
}
希望这有帮助,尊重
答案 1 :(得分:3)
您可以使用EnumWindows查找每个顶级Chrome窗口,然后递归调用EnumChildWindows (请参阅Jeroen Wiert Pluimers的评论)得到主窗口的每个孩子。或者,一旦您拥有主Chrome窗口,您就可以使用GetWindow手动导航树,因为您可能知道您正在寻找的内容(第3个孩子的儿童集合或类似内容)。
找到窗口后,可以使用带有WM_GETTEXT参数的SendMessage来读取窗口的标签。
答案 2 :(得分:3)
查看本文here,其中包含有关托管间谍的信息以及作者编写该工具的原因。
答案 3 :(得分:2)
您可以使用HWndSpy。源代码是here。
答案 4 :(得分:1)
用于指向窗口的功能。您需要SetCapture()
,以便获得窗口外的鼠标消息。然后使用WindowFromPoint()
将鼠标位置转换为Window。您需要首先将moust位置从客户端坐标转换为窗口坐标。
如果您在鼠标单击消息的任何地方尝试呼叫SetCapture()
,您可能会被忽略。这就是Spy ++让你点击一个Icon并将其拖放到你想指向的窗口上的原因。