首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Snoop使用什么技术来检查WPF应用程序?

Snoop使用什么技术来检查WPF应用程序?
EN

Stack Overflow用户
提问于 2014-06-04 18:43:22
回答 4查看 3.5K关注 0票数 11

间谍工具Snoop使用一些强大的技术(可能是某种反射)来检查正在运行的WPF应用程序。最有趣的是,Snnop能够读取整个对象结构。

几天前,我下载了Snoop源代码,并花了一些时间研究内部行为。不幸的是,我还没有弄清楚Snoop是如何做这些事情的,所以我希望任何人都能帮助我。

在工作中,我目前正在编写一个编码的UI测试-框架,如果我能够访问应用程序的对象结构,那就太棒了,因为这将允许我不仅断言UI状态。

更新:

这是所需的代码:

代码语言:javascript
复制
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是如何将自己注入到另一个进程中的。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2014-06-04 19:04:09

您可以通过使用WPF VisualTreeHelper和/或LogicalTreeHelper来完成Snoop的工作。一旦您获得任何视觉元素,您几乎可以遍历它的整个视觉树来查看它包含的所有元素。可视化树辅助器这里

因此,在您的UI测试中,抓取主窗口并遍历它的可视树以找到您想要的任何元素,然后对该元素执行任何验证或操作。

此外,您还可以使用System.Diagnostics.Process.MainWindowHandle从现有进程获取窗口句柄,然后使用该窗口的句柄创建一个wpf窗口。已经有一段时间了,所以我不记得细节,除非做更多的研究。下面的守则可能会有所帮助:

代码语言:javascript
复制
Window window = (Window)System.Windows.Interop.HwndSource.FromHwnd(process.MainWindowHandle).RootVisual;
票数 3
EN

Stack Overflow用户

发布于 2014-06-05 18:53:30

更新:

好的,我找到了基本的代码位置,这是Snoop用来提供注入能力的。令我惊讶的是,代码是编写的C++/CLI。也许这是有原因的。

这就是代码(我希望可以在这里发布):

代码语言:javascript
复制
//-----------------------------------------------------------------------------
//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);
    }
}
票数 3
EN

Stack Overflow用户

发布于 2015-03-06 19:53:02

Snoop不会从外部检查WPF。它将自身注入到应用程序中,并实际上向其添加了放大镜或窥探窗口。这也是为什么当你退出窥探检查窗口实际上保持打开。

因此,“检查”代码只需检查它想要的窗口,它就可以使用所有可用的WPF函数进行检查。就像前面提到的VisualTreeHelper和LogicalTreeHelper一样。

对于一个小型测试框架,我注入了代码以添加一个小型代理对象,这样我就可以轻松地控制应用程序(按按钮、更改值、在视图模型上执行函数等等)。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24045183

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档