본문 바로가기
Programming/Tips(C++,C#)

C#에서 IE띄워서 핸들링하기

by 곰네Zip 2016. 7. 7.

밑에 포스팅에서 작업을 할 때에.. WebBrowser를 사용해서 작업했는데..

ActiveX컨트롤을 불렀을 때 비정상 종료되는 문제가 있었다. (원인은 파악은 안되나. activeX컨트롤이 올라오면 발생했음. 내가 만든 ActiveX가 아니니..)

 

그래서 차선책(?)으로 IE를 직접 불러서 작업하기로.

해야할 것

 1. 웹페이지를 연동한다. (Post전송사용)

 2. 페이지가 로딩되면 해당 HTML에 조작(-_-)을 한다.

 

 using SHDocVw;

 using mshtml;

 -> 이 두개를 사용하기 위해서..

  Microsoft HTML ObjectLibrary(mshtml)

  Microsoft Internet Controls (SHDocVw)

 를 참조 추가.

 

 우선 IE를 만들자. 사용방법은 WebBrowser랑 비슷하다. 단, COM에 넘겨주는거라 string이 아니라 ref object형태로 넘겨야 한다. 사용하고 넘기는 방법은 아래와 같다.

void showIE(){

 SHDocVw.InternetExplorer ie = new SHDocVw.InternetExplorer(); //internet explorer 개체. HTML불러오기 위해서 필요하다.

 SHDocVw.IWebBrowserApp wb = ie as  SHDocVw.IWebBrowserApp;

 ie.DocumentComplete += LoadDocCompleteFunc();

 

//Post전송을 위한 데이터 전달

 object flag = 0;

 object targetframe = 0;

 object postData = Encoding.UTF8.GetBytes(strPostData); //인코딩타입은 필요한거에 따라 호출

 object contentType = "Content-Type: application/x-www-form-urlencoded" + Convert.ToChar(10) + Convert.ToChar(13);

 //웹페이지 크기설정

 wb.width = Forms.PrimaryScreen.Bounds.Width; //주모니터 너비

 wb.height = Forms.PrimaryScreen.Bounds.Height; //주모니터 높이

 wb.Visible = true;

 wb.Navigate(URL, ref flag , ref targetframe, ref postData, ref contentType);

}

 이렇게 하면 IE창 띄우기는 성공! 단, documentcomplete 이벤트를 처리하려면.. ie는 멤버로 가지고 있는게 좋을듯. ie의 경우 정상적으로 창을 닫게되면 알아서 메모리에서 해제되고, 한번 생성했으니까 다음에는 new를 이용해서 InternetExplorer생성 안해도 되겠지.. 하면 오류를 만날 수 있다. 단, ie가 정상적으로 종료되지 않을경우 찌꺼기가 남아있는데.. 이에 대한 처리는 필요하다. (이는 구글신에게 물어보면 레퍼런스 많으므로 스킵)

 만약 IE창이 닫힐 때, 처리를 하고자 하는게 있다면 OnQuit에 이벤트 걸어서 처리하면 됨.

 

 이벤트 처리 함수는 아래와 같다. WebBrowser에서 Document를 Forms.HtmlDocument, HtmlElement로 가져와서 쓰는거랑 비슷하다. (함수명도..) 그러나 약간의 차이는 있다.

 void LoadDocCompleteFunc(object pDisp, ref object URL){

    mshtml.IHTMLDocument3 htmlDoc = ie.Document as mshtml.IHTMLDocument3;

    if( htmlDoc == null){ return; }

    mshtml.IHTMLElement elem1 = htmlDoc.getElementById("이름");

    if( elem1 != null){

       elem1.setAttribute("속성명","값");

    }

 }

 위에서 확인할 수 있듯이, 호출하는 함수명은 비슷하지만 시작이 소문자다. 그리고 엘리먼트를 가져오려면 IHTMLDocument3로..

 

 * 이렇게 호출할 경우 만약, 창이 닫힐때까지 대기해야 할 필요가 있을경우 ManualResetEvent를 사용하여 기다리게 하면 된다. 대략적인 방법은 아래와 같다.

public class MyClass{

  private EventWaitHandle myHandle = null;

  void StartNavigate(){

    if(myHandle == null){ myHandle = new ManualResetEvent(false); }

    myHandle.Reset(); //신호없음 상태로 설정

    ShowIE();

    myHandle.waitOne(); //신호있음 상태 될때까지 대기하자.

  }

  void ShowIE(){

    ie.OnQuit += IEClosed;

     ...

  }

  void IEClosed(){

     myHandle.set(); //신호있음으로 설정.

  }

 Reset으로 설정한 후, waitOne을 하면 해당 스레드는 대기한다. 그러다 IE가 Close되서 이벤트가 Set되면 이후 진행을 한다. (물론 저 Navigate를 호출하기 전에 별도의 스레드로 분리하자. )

반응형

댓글