[C++/WinAPI] Dostęp do stron otwartych w IE.

0

Problem jak w temacie. Potrzebuję odczytać w programie stronę otwartą przez InternetExplorer. Obecnie wykorzystuję do tego funkcję GetUrlCacheEntryInfo do pobrania nazwy pliku w wirtualnym katalogu Temporary Internet Files. Wszystko jest prawie w porządku, ale... Chodzi o to, że nie wszystkie strony zapisują się w cache przeglądarki. Powodem jest to, że mają parametr no-cache, który na to nie pozwala. Ponadto chodzi mi o strony generowane dynamicznie przez JavaScript. Czy jest jakaś możliwość odczytania strony bezpośrednio z pamięci przeglądarki? Właśnie takiej, na której już interpreter wykona odpowiednie instrukcje z języka skryptowego.

0

Może hook na okno IE?

0
#include <ole2.h>
#include <mshtml.h>
#include <oleacc.h> // ObjectFromLresult
#include <stdio.h>  // printf



BOOL __stdcall EnumWindowsProc(HWND hwnd, UINT nMsg)
{
	char classname[64];
	classname[0] = 0;
	GetClassName(hwnd, classname, 64);

	if (!strcmp(classname, "Internet Explorer_Server"))
	{
		DWORD dwResult;
		IHTMLDocument2 *spDoc;
		SendMessageTimeout(hwnd, nMsg, 0, 0, SMTO_ABORTIFHUNG, 1000, &dwResult);

		if (!ObjectFromLresult(dwResult, IID_IHTMLDocument2, 0, (void**)&spDoc ))
		{
			BSTR bstrUrl = NULL; // potrzebujesz url ?
			// url w devcpp małymi literami :o
			if (!spDoc->get_url(&bstrUrl) && (bstrUrl))
			{
				// to uzyj go tu
				printf("%S\n", bstrUrl);
				SysFreeString(bstrUrl);
			}
			//ZapiszHTML(spDoc);
			spDoc->Release();
		}
	}
	return TRUE; // nastepne okno
}



int main()
{
	UINT nMsg = RegisterWindowMessage("WM_HTML_GETOBJECT");

	CoInitialize(NULL);
	EnumChildWindows(GetDesktopWindow(), (WNDENUMPROC)EnumWindowsProc, nMsg);
	CoUninitialize();
	system("pause");
	return 0;
}

Funkcje ZapiszHTML(IHTMLDocument2 *) musisz sam naskrobac zaleznie co chcesz zrobic. Jak wydobyc pelny kod HTML juz raz pisalem w dziale newbie pod buildera, szukaj za IHTMLDocument2, get_innerHTML ...

0

Mam parę pytań, bo temat nagle zrobił się gorący...
UINT nMsg = RegisterWindowMessage("WM_HTML_GETOBJECT");
Po co ten komunikat, co on oznacza?
Czy jak mam uchwyt okna pobrany z nazwy, to muszę używać EnumChildWindows i callback?
Czy da się to skompilować w DevCpp? Jak na razie wywala mi błędy. Próbowałem też z kodem z adresu:
http://www.coderscity.net/ntopic9654.html i też nie działa.
Wywala mi
[Linker Error] undefined reference to `IID_IHTMLDocument2'

0

IID_IHTMLDocument2 znajdziesz w libuuid.a, wystarczy poszukać w plikach. Linkuj też z liboleacc.a.
"get_URL" może będziesz musiał zmienić na "get_url" bo ktoś miał wizję że tak będzie lepiej.
Powyższy kod updated :)
WM_HTML_GETOBJECT - przeczytaj w MSDN bo szkoda przepisywać.
Te program wyłapie każde okno które korzysta z silnika IE, nawet te z GG, a ze skompilowaniem w devcpp nie było problemów.

0

Dzięki bardzo. Teraz prawie działa...
Jeszcze mi nie może zlinkować SysFreeString. Szukałem na msdn, ale wywala, że nie ma strony, albo nie ma opisu do requaire i nie wiem co zlinkować.
//EDIT: Ale już znalazłem, że liboleaut32.a, więc jest oki.
Mam jeszcze taką jedną wątpliwość, ale dziś już nie sprawdzę tego z braku możliwości. Czy na IE7 też to zadziała? Tam przecież jest tylko jedno okno przeglądarki i wiele zakładek, to jak znajdzie wszystkie?

0

Na pewno zadziała. Każda zakładka jest traktowana jako oddzielne "okno" korzystające z silnika. To, że strony są otwarte na jednej, hmmm... "formie", nie zmienia sytuacji. Do każdej strony masz dostęp przez oddzielny uchwyt. Tak to oceniam na 99,9%

0

Mam coś takiego:

spDoc->get_body(&element);
                            element->get_innerHTML(&bstrUrl);
                            element->Release();
                                printf("%S\n", bstrUrl);
                                SysFreeString(bstrUrl);

I wypisuje mi na ekran zawartość z body. Mam dziwne wrażenie, że uzyskanie całego tekstu html będzie już łatwe, ale jeszcze nie mam pomysłu jak to zrobić. Szukałem na forum, bo miało być, ale jakoś nie udało mi się znaleźć. Były podobne tematy, ale dokładnie tego nie. Więc jakbym mógł poprosić o wskazówki (że nie wspomnę o gotowym kodzie :) ) jak napisać funkcję, która z IHTMLDocument2 zrobi mi c_str, albo coś podobnego.

0

Wbrew pozorom, praca z WebBrowser jest trochę bardziej męcząca w Builderze niż w Delphi, więc Ci kod rzucę - sam tego kodu trochę szukałem, więc zaoszczędzę ci kilku godzin kombinowania:

AnsiString GetSource(TCppWebBrowser* Browser) {
    AnsiString Source;
    IHTMLDocument2* HTMLDoc;
    IPersistStreamInit *persist = NULL;
    IStream *stream = NULL;

    Browser->Document->QueryInterface(IID_IHTMLDocument2, (void**)&HTMLDoc);
    HTMLDoc->QueryInterface(IID_IPersistStreamInit, (void**)&persist);
    CreateStreamOnHGlobal(NULL, true, &stream);

    __int64 nSize = 0;
    STATSTG ss;
    LARGE_INTEGER nMove;
    nMove.QuadPart = 0;
    persist->Save(stream, true);
    stream->Seek(nMove, STREAM_SEEK_SET, (ULARGE_INTEGER*)&nSize);
    stream->Stat(&ss, STATFLAG_NONAME);
    nSize = ss.cbSize.QuadPart;

    Source.SetLength(nSize);
    stream->Read((void*)Source.data(), nSize, (ULONG*)&nSize);

    stream->Release();
    persist->Release();
    HTMLDoc->Release();

    return Source;
    }

Podobno, żeby to działało trzeba wstawić poniższe nagłówki - jakkolwiek mi wystarczyło samo mshtml:

#include <mshtml.h>
#include <ocidl.h>
#include <objidl.h>

Edit:
A wróć - ja nie wiem, czy ty używasz Buildera - przyjąłem to w domyśle :D Tak czy inaczej, rzuć na to okiem, może naprowadzi ;)

0

Oki. Wspólnym sumptem z sapero i Ranidesem udało mi się sklecić programik, który robi to co powinien i będzie podstawą do wykorzystania we właściwym programie. Poza kodem przedstawionym powyżej, po niewielkich zmianach, dodałem od siebie funkcję, która wyciąga strony z ramek, jeżeli takie znajdzie. Program wyrzuca na ekran adres strony i kod html. Jeżeli strona zawiera ramki, to wyświetla również adres żródła ramki i to źródło. Jeżeli ramki będą zagnieżdżone, to też powinno zadziałać.
Kod kompiluje się pod DevCpp. W opcjach projektu neleży jeszcze dodać biblioteki do zlinkowania:
C:/Dev-Cpp/lib/libuser32.a
C:/Dev-Cpp/lib/libole32.a
C:/Dev-Cpp/lib/liboleacc.a
C:/Dev-Cpp/lib/libuuid.a
C:/Dev-Cpp/lib/liboleaut32.a

#include <ole2.h>
#include <mshtml.h>
#include <oleacc.h> // ObjectFromLresult
#include <stdio.h>  // printf
#include <ocidl.h>
#include <objidl.h>
/*
Requires Active Accessibility 2.0 RDK on Windows NT 4.0 SP6 and Windows 98.
*/

char* GetSource(IHTMLDocument2* HTMLDoc) {
    char* Source;
    IPersistStreamInit *persist = NULL;
    IStream *stream = NULL;
    HTMLDoc->QueryInterface(IID_IPersistStreamInit, (void**)&persist);
    CreateStreamOnHGlobal(NULL, true, &stream);
    __int64 nSize = 0;
    STATSTG ss;
    LARGE_INTEGER nMove;
    nMove.QuadPart = 0;
    persist->Save(stream, true);
    stream->Seek(nMove, STREAM_SEEK_SET, (ULARGE_INTEGER*)&nSize);
    stream->Stat(&ss, STATFLAG_NONAME);
    nSize = ss.cbSize.QuadPart;
    //printf("%d\n", nSize);
    Source=new char[nSize+1];
    Source[nSize]=0;
    stream->Read((void*)Source, nSize, (ULONG*)&nSize);
    //printf("%d\n", nSize);
    stream->Release();
    persist->Release();
    return Source;
    }
////////////////////////////////////////////////////////////////////////////////
void Info(IHTMLDocument2* spDoc){
                        BSTR bstrUrl = NULL;
                        if (!spDoc->get_url(&bstrUrl) && (bstrUrl))
                        {
                                printf("%S\n\n", bstrUrl);
                                SysFreeString(bstrUrl);
                        }
                           char*s= GetSource(spDoc);
                                printf("%s\n\n\n\n", s);
                                delete [] s;

                        IHTMLFramesCollection*fc=NULL;
                        IHTMLFramesCollection2*fc2=NULL;

                        spDoc->get_frames(&fc);
                        if(fc){
                            long p;
                            fc2=(IHTMLFramesCollection2*)fc;
                            fc2->get_length(&p);

                         for(long i=0; i<p; i++){
                                VARIANT frameRequested;
                                VARIANT frameOut;
                                IHTMLWindow2* pFrameWindow;
                                IHTMLDocument2* pDoc;
                                HRESULT hr;
                                frameRequested.vt = VT_I4;
                                frameRequested.lVal = i;
                                hr = fc2->item(&frameRequested, &frameOut);
                                hr = frameOut.pdispVal->QueryInterface(IID_IHTMLWindow2, (void**)&pFrameWindow);
                                hr = pFrameWindow->get_document(&pDoc);
                                Info(pDoc);
                            }//end for i
                        fc2->Release();
                        }
}
////////////////////////////////////////////////////////////////////////////////
BOOL __stdcall EnumWindowsProc(HWND hwnd, UINT nMsg)
{
        char classname[64];
        classname[0] = 0;
        GetClassName(hwnd, classname, 64);

        if (!strcmp(classname, "Internet Explorer_Server"))
        {
                DWORD dwResult;
                IHTMLDocument2 *spDoc;
                SendMessageTimeout(hwnd, nMsg, 0, 0, SMTO_ABORTIFHUNG, 1000, &dwResult);
                if (!ObjectFromLresult(dwResult, IID_IHTMLDocument2, 0, (void**)&spDoc ))
                {
                       Info(spDoc);
                        spDoc->Release();
                }
        }
        return TRUE; // nastepne okno
}
int main()
{
        UINT nMsg = RegisterWindowMessage("WM_HTML_GETOBJECT");
        CoInitialize(NULL);
        EnumChildWindows(GetDesktopWindow(), (WNDENUMPROC)EnumWindowsProc, nMsg);
        CoUninitialize();
        //system("pause");
        return 0;
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1