|
qwer 님이 쓰신 글 :
: 웹 브라우저를 이용해 HTML을 읽어온 뒤 HTML을 파일로 저장 후 파싱을 통해 특정 패턴을 찾아내는 프로그램을 만들려고 합니다. 게시판에 올라온 많은 분들의 TCppWebBrowser를 사용한 웹 브라우저 소스를 참고했는데 실행 시 메모리 참조 에러가 납니다. 초보인 저로써는 도대체 뭐가 잘못된 것인지 알수가 없네요.
: 고수분들의 도움을 바랍니다.
:
: 아래는 참고한 소스입니다.
:
:
: ==================================================================================================
: IDispatch *pDocument=CppWebBrowser1->Document;
: IHTMLElement *HTMLElement;
: IHTMLDocument2 *pDoc;
: HRESULT hr;
:
: WideString HTML;
: WideString Text;
:
: hr = pDocument->QueryInterface(IID_IHTMLDocument2, (void**)pDoc); <== 요기서 에러가 납니다.
: if(hr == S_OK)
: {
: hr = pDoc->get_body(&HTMLElement);
: if(hr == S_OK)
: {
: HTMLElement->get_innerHTML(&HTML);
: HTMLElement->get_innerText(&Text);
: HTMLElement->Release();
: }
: pDoc->Release();
: }
: Memo1->Lines->Clear();
: Memo1->Lines->Add(HTML);
: ==================================================================================================
CppWebBrowser1->Navigate((WideString)url);
if(!CppWebBrowser1->Document){
ShowMessage("CppWebBrowser1->Document is NULL !!!");
return;
}
IHTMLDocument2 *ihtmldc;
HRESULT hresult = CppWebBrowser1->Document->QueryInterface(IID_IHTMLDocument2,(void**)&ihtmldc);
위에서와 같이 Navigate 직후에 CppWebBrowser1->Document->AMember 를 하게 되면
CppWebBrowser1->Document가 NULL일 수 있으므로 오류가 발생할 수 있습니다.
Navigate 메서드는 non-blocking입니다.
즉, Navigate를 호출하면 요청한 페이지가 다운로드되기 전에 Navigate에서 복귀(return)할 수 있습니다.
따라서, 아래와 같이 OnDocumentComplete 의 이벤트 핸들러 내에서 작업하는 게 안전합니다.
//프레임마다 한 번씩 이 이벤트 핸들러가 호출됨(프레임수 + 1 번 호출됨)
//프레임으로 나뉘어져 있지 않으면 한 번만 호출됨
void __fastcall TForm1::CppWebBrowser1DocumentComplete(TObject *Sender,
LPDISPATCH pDisp, Variant *URL)
{
Variant webbrowserframe=Unassigned,HTMLDoc=Unassigned,Body=Unassigned;
try{
webbrowserframe = pDisp;
HTMLDoc=webbrowserframe.OlePropertyGet("Document");
if ( !VarIsEmpty( HTMLDoc ) )
{
Body = HTMLDoc.OlePropertyGet("Body");
if ( !VarIsEmpty( Body ) )
{
if(pDisp==CppWebBrowser1->ControlInterface)
{
//페이지는 프레임으로 나뉘어져 있을 수 있는데, 모든 프레임이 다운로드되면 이 곳으로 들어오게 됨
//프레임으로 나뉘어져 있지 않아도 이 곳으로 들어옴
//String((String)Body.OlePropertyGet("InnerHTML"));
}
else
{
//프레임으로 나뉘여져 있는 경우 프레임 별 작업
//String((String)Body.OlePropertyGet("InnerHTML"));
}
}
}
}catch(...){
}
VarClear(Body);
VarClear(HTMLDoc);
VarClear(webbrowserframe);
|