Question

Snoop, l'utilitaire d'espionnage, utilise une technique puissante (probablement une sorte de réflexion) pour inspecter une application WPF en cours d'exécution.Le plus intéressant est le fait que Snnop est capable de lire la structure de l'objet entière.

Il y a quelques jours, j'ai téléchargé le code source Snoop et j'ai passé du temps à étudier le comportement interne.Malheureusement, je n'ai pas encore pu le découvrir comment Snoop fait ces choses, alors j'espère que tout le monde peut m'aider.

Au travail, j'écris actuellement un cadre de test de l'interface utilisateur codée et il serait fantastique si j'avais accès aux structures d'objet de l'application, car cela me permettrait de non seulement affirmer l'état de l'interface utilisateur.

mise à jour:

Ceci est le code nécessaire:

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;

Ceci est déjà une grande aide pour moi, mais il est également intéressant de le savoir, comment Snoop s'inspecte dans un autre processus.

Autres conseils

mise à jour:

D'accord, j'ai trouvé l'emplacement de base du code, utilisé par Snoop pour fournir la capacité d'injection.À mon étonnement que le code est écrit C. probablement il y a une raison de.

Et c'est le code (j'espère qu'il est correct de la publier ici):

//-----------------------------------------------------------------------------
//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 n'inspire pas de WPF de l'extérieur.Il s'affiche dans l'application et ajoute en réalité la fenêtre magnifiée ou snoop.C'est aussi pourquoi quand vous quittez Snoop, les fenêtres d'inspection restent ouvertes.

Le code "inspection" inspecte simplement la fenêtre qu'il souhaite et il peut utiliser toutes les fonctions WPF disponibles pour le faire.Comme le menu VisualTeeheHelper et LogicalTeheHelper comme mentionné ici plus tôt.

Pour un petit cadre de test, je construit un code injecté pour ajouter un petit objet proxy afin que je puisse contrôler facilement l'application (appuyez sur les touches, modifier les valeurs, exécuter des fonctions dans la vue Modèles etc.).

La réponse ci-dessus ne fonctionne pas pour moi.Cela semble un peu vague.J'ai étendu un peu de réponse acceptée avec ce code:

    var allProcesses = Process.GetProcesses();
    var filteredProcess = allProcesses.Where(p => p.ProcessName.Contains(ProcessSearchText)).First();
    var windowHandle = filteredProcess.MainWindowHandle;
    var hwndSource = HwndSource.FromHwnd(windowHandle);

Cette réponse semble plus complète et fonctionnera pour d'autres si la réponse acceptée fonctionne pour quiconque.Cependant, cette dernière ligne de ce code retourne null pour moi.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top