Snoop은 WPF 응용 프로그램을 검사하는 데 사용하는 기술
-
21-12-2019 - |
문제
snoop, SPY 유틸리티는 실행중인 WPF 응용 프로그램을 검사하기 위해 일부 강력한 기술 (아마도 일종의 반사)을 사용합니다.SNNOP는 전체 객체 구조를 읽을 수있는 사실입니다.
며칠 전 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;
.
이것은 이미 나에게 큰 도움이되지만, 스눕이 어떻게 다른 프로세스를 주입하는지 알아내는 것이 흥미 롭습니다.
해결책
WPF VisualTreeHelper 및 / 또는 LogicalTreeHelper를 사용하여 Snoop이 수행하는 작업을 수행 할 수 있습니다.어떤 시각적 요소를 보유하고 있으면 전체 시각적 트리를 꽤 많이 트래버스하여 모든 요소를 볼 수 있습니다.Visual Tree Helper 여기 <./ a>
그래서 UI 테스트에서 기본 창을 잡고 시각적 트리를 트래버스하여 원하는 요소를 찾은 다음 해당 요소에서 원하는 유효성 검사 또는 작업을 수행합니다.
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를 검사하지 않습니다.응용 프로그램에 주입하고 실제로 확대 또는 스눕 창을 추가합니다.그게 또한 스눕을 빠져 나올 때 검사 창은 실제로 열려 있습니다.
그래서 '검사'코드는 단순히 원하는 창을 검사하고 모든 Avaible WPF 기능을 사용할 수 있도록 사용할 수 있습니다.여기에 언급 한 바와 같이 VisualTreeHelper와 LogicalTreeHelper와 마찬가지로
작은 테스트 프레임 워크의 경우 i를 빌드하여 작은 프록시 오브젝트를 추가하여 응용 프로그램을 쉽게 제어 할 수 있도록 (버튼, 값 변경, ViewModels에서 기능 실행 기능을 눌러) 할 수 있습니다.
위의 대답은 나를 위해 작동하지 않습니다.조금 모호한 것 같습니다.이 코드로 조금 받아 들여지는 답변을 받아 들였습니다.
var allProcesses = Process.GetProcesses();
var filteredProcess = allProcesses.Where(p => p.ProcessName.Contains(ProcessSearchText)).First();
var windowHandle = filteredProcess.MainWindowHandle;
var hwndSource = HwndSource.FromHwnd(windowHandle);
.
이 답변은 더 완전 해져서 받아 들여지는 답변이 누구에게나 작동하는 경우 다른 사람들을 위해 일할 것입니다.그러나이 코드의 마지막 줄은 나에게 null을 반환합니다.