Domanda

Snoop, l'utilità Spy, utilizza una tecnica potente (probabilmente una sorta di riflessione) per ispezionare un'applicazione WPF in esecuzione.Più interessante è il fatto che SnNOP è in grado di leggere l'intera struttura dell'oggetto.

pochi giorni fa ho scaricato il codice sorgente snoop e ho trascorso un po 'di tempo per studiare il comportamento interno.Sfortunatamente, non riuscivo a scoprire che come snoop sta facendo queste cose, quindi spero che qualcuno possa aiutarmi.

Al lavoro attualmente sto scrivendo un framework-quadro dell'interfaccia utente codificato e sarebbe fantastico se avessi accesso alle strutture dell'oggetto dell'applicazione perché questo mi consentirebbe di non solo affermare lo stato dell'interfaccia utente.

Aggiornamento:

Questo è il codice necessario:

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;
.

Questo è già un grande aiuto per me, ma è anche interessante scoprire, come snoop si inietta in un altro processo.

Altri suggerimenti

Aggiornamento:

Okay, ho trovato la posizione di codice di base, che viene utilizzata da Snoop per fornire la capacità di iniezione.Per il mio stupore che il codice è scritto C. Probabilmente c'è una ragione per.

E questo è il codice (spero che sia bene postarlo qui):

//-----------------------------------------------------------------------------
//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 non ispeziona un WPF dall'esterno.Si inienta nell'applicazione e effettivamente aggiunge la finestra di ingrandimento o snoop.Questo è anche il motivo per cui quando esci da snoop le finestre di ispezione rimangono in realtà aperte.

Quindi il codice "Ispezione" ispeziona semplicemente la finestra che desidera e può utilizzare tutte le funzioni Avabili WPF per farlo.Come il VisualtreeHelper e LogaltreeHelper come menzionato qui prima.

Per un piccolo framework di prova Costruire il codice iniettato per aggiungere un piccolo oggetto proxy in modo da poter controllare facilmente l'applicazione (premere i pulsanti, i valori di modifica, eseguire funzioni su viewModels ecc.).

La risposta sopra non funziona per me.Sembra un po 'vago.Ho ampliato una risposta accettata un po 'con questo codice:

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

Questa risposta sembra più completa e lavorerà per gli altri se la risposta accettata funziona per nessuno.Tuttavia, questo l'ultima riga di questo codice restituisce NULL per me.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top