Я интересуюсь работой над плагином для Keepass, менеджера паролей с открытым исходным кодом. Прямо сейчас Keepass в настоящее время обнаруживает то, что пароль к скопировать/вставить для Вас основывал прочь заголовка окна. Это препятствует тому, чтобы Keepass обнаружил текущий пароль, в котором Вы нуждаетесь для приложений, которые активно не обновляют их заголовок окна на основе текущего сайта (Chrome, например).
Как я могу обойти через другое окно процессов элементы (кнопки, маркировки, текстовое поле) подобный тому, как Шпион ++ работает? При выполнении Шпиона ++, можно нависнуть над другими окнами программ и получить все виды информации о различных свойствах относительно различных средств управления (маркировки, текстовые поля, и т.д.). Идеально, я хотел бы, чтобы мой плагин Keepass улучшил текущее обнаружение окна путем обхода через элементы активного окна, чтобы найти учетную запись соответствия к скопировать/вставить паролю.
Как я могу обойти другие элементы окна процессов и быть в состоянии получить маркировку и значения текстового поля с помощью C#?
Я тут отвечаю на подобные вопросы: Как я могу определить, есть ли у нити оконные ручки? . Как и говорится, основная идея заключается в том, чтобы перечислить через окна процесса и их дочерние окна, используя EnumWindows и EnumChildWindows API вызовы, чтобы получить оконные дескрипторы, а затем вызвать GetWindowText или SendDlgItemMessage с помощью WM_GETTEXT, чтобы получить текст окна. Я модифицировал код, чтобы сделать пример, который должен делать то, что нужно (извините, он немного длинный :). Он итератует через процессы и их окна и сбрасывает текст окна в консоль.
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;
}
надеемся, что это поможет, уважаемый
. Вы можете использовать EnumWindows, чтобы найти каждое окно Chrome верхнего уровня, а затем вызвать EnumChildWindows рекурсивно (см. комментарий Jeroen Wiert Pluimers), чтобы получить каждого дочернего элемента главного окна. В качестве альтернативы, как только у вас будет главное окно Chrome, вы можете использовать GetWindow для ручной навигации по дереву, так как вы, вероятно, знаете, что вы ищете (3-я дочерняя коллекция или что-то подобное).
Как только вы найдёте своё окно, вы можете использовать SendMessage с параметром WM_GETTEXT для считывания метки окна.
.Посмотрите на эту статью здесь , которая содержит информацию об управляемом шпионе и о том, почему автор написал этот инструмент.
. Для функциональности наведения на окно. Вам необходимо SetCapture()
, чтобы получить сообщения мыши, которые находятся за пределами вашего окна. Затем используйте WindowFromPoint()
для преобразования положения мыши в окно. Сначала необходимо преобразовать положение мыши из координат клиента в координаты окна.
Если вы попробуете вызвать SetCapture()
где угодно, но только не при щелчке мышью, то, скорее всего, вас проигнорируют. По этой причине Spy++ заставляет вас нажать на иконку и перетащить ее в окно, на которое вы хотите навести.