Какую технику использует Snoop для проверки приложения WPF
-
21-12-2019 - |
Вопрос
Snoop, Spy Utility, использует некоторую мощную технику (вероятно, какое-то отражение) для проверки запущенного приложения WPF.Самое интересное - это тот факт, что SNNOP может считать всю структуру объекта.
Несколько дней назад я загрузил исходный код Snoop и провел некоторое время на изучение внутреннего поведения.К сожалению, я не мог узнать, как Snoop делает эти вещи, поэтому я надеюсь, что кто-нибудь может помочь мне.
На работе я в настоящее время пишу код тестирования закодированных пользовательских интерфейсов, и было бы фантастическим, если бы у меня был доступ к объектам приложения, потому что это позволит мне не только утверждать состояние UI.
Обновление:
Это код необходим:
string filePath = "WpfApp.exe";
AppDomain appDomain = AppDomain.CurrentDomain;
byte[] bytes = System.IO.File.ReadAllBytes(filePath);
Assembly ass = appDomain.Load(bytes);
ass.EntryPoint.Invoke(null, new object[] { });
IntPtr handle = Process.GetCurrentProcess().MainWindowHandle;
Window w = System.Windows.Interop.HwndSource.FromHwnd(handle).RootVisual as Window;
.
Это уже большая помощь для меня, но также интересно выяснить, как Snoop вводит себя в другой процесс.
Решение
Вы можете выполнить то, что Snoop делает, используя WPF VisualTreehehelper и / или логикателера.Как только вы получите удержание любого визуального элемента, вы можете в значительной степени пройти все это визуальное дерево, чтобы увидеть все элементы, которые он содержит.Visual Tree Helper здесь
Кроме того, вы можете использовать System.diagnostics.process.mainwindowhandle, чтобы получить обрабатывать Windows из существующего процесса, а затем использовать ручку окна для создания окна WPF.Это было некоторое время, поэтому я не помню специфику, не делая больше исследований.Код ниже может помочь:Window window = (Window)System.Windows.Interop.HwndSource.FromHwnd(process.MainWindowHandle).RootVisual;
. Другие советы
Обновление:
Хорошо, я нашел основное местоположение кода, которое используется Snoop, чтобы обеспечить способность инъекции.К моему удивлению, этот код написан C. Вероятно, есть причина.
и это код (я надеюсь, что это в порядке, чтобы опубликовать его здесь):
//-----------------------------------------------------------------------------
//Spying Process functions follow
//-----------------------------------------------------------------------------
void Injector::Launch(System::IntPtr windowHandle, System::String^ assembly, System::String^ className, System::String^ methodName)
{
System::String^ assemblyClassAndMethod = assembly + "$" + className + "$" + methodName;
pin_ptr<const wchar_t> acmLocal = PtrToStringChars(assemblyClassAndMethod);
HINSTANCE hinstDLL;
if (::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCTSTR)&MessageHookProc, &hinstDLL))
{
LogMessage("GetModuleHandleEx successful", true);
DWORD processID = 0;
DWORD threadID = ::GetWindowThreadProcessId((HWND)windowHandle.ToPointer(), &processID);
if (processID)
{
LogMessage("Got process id", true);
HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, processID);
if (hProcess)
{
LogMessage("Got process handle", true);
int buffLen = (assemblyClassAndMethod->Length + 1) * sizeof(wchar_t);
void* acmRemote = ::VirtualAllocEx(hProcess, NULL, buffLen, MEM_COMMIT, PAGE_READWRITE);
if (acmRemote)
{
LogMessage("VirtualAllocEx successful", true);
::WriteProcessMemory(hProcess, acmRemote, acmLocal, buffLen, NULL);
_messageHookHandle = ::SetWindowsHookEx(WH_CALLWNDPROC, &MessageHookProc, hinstDLL, threadID);
if (_messageHookHandle)
{
LogMessage("SetWindowsHookEx successful", true);
::SendMessage((HWND)windowHandle.ToPointer(), WM_GOBABYGO, (WPARAM)acmRemote, 0);
::UnhookWindowsHookEx(_messageHookHandle);
}
::VirtualFreeEx(hProcess, acmRemote, 0, MEM_RELEASE);
}
::CloseHandle(hProcess);
}
}
::FreeLibrary(hinstDLL);
}
}
. snoop не проверяет WPF снаружи.Он вводит себя в приложение и фактически добавляет окно увелича или Snoop.Это также почему, когда вы выходите на Snoop, окна проверки на самом деле остаются открытыми.
Так что код «проверки» просто проверяет окно, которое он хочет, и он может использовать все операторы WPF для этого.Как визуальный элемент и логикатреннее, как упомянуто здесь ранее.
Для небольшой тестовой структуры, которую я строит, я вводил код, чтобы добавить небольшой прокси-объект, чтобы я мог легко управлять приложением (нажмите кнопки, изменять значения, выполнять функции на ViewModels и т. Д.).
Ответ выше не работает для меня.Кажется немного расплывчатым.Я немного расширился на принятый ответ с этим кодом:
var allProcesses = Process.GetProcesses();
var filteredProcess = allProcesses.Where(p => p.ProcessName.Contains(ProcessSearchText)).First();
var windowHandle = filteredProcess.MainWindowHandle;
var hwndSource = HwndSource.FromHwnd(windowHandle);
.
Этот ответ кажется более полным и будет работать для других, если у кого-либо работает принятый ответ.Однако эта последняя строка этого кода возвращает нуль для меня.