How to customize a 12306 ticket grabbing browser -- start the "person" Thread

Source: Internet
Author: User

First, we need to clarify what COM object is passed. In general, if we want to manipulate pages in the browser, they all start from the IWebBrowser interface object. Here we also want to pass this interface object [cpp] VOID SetWebBrowser (CComPtr <IWebBrowser2> & spWeb); next we need to specify when to pass the IWebBrowser interface object. I have selected the DocumentComplete message to notify the "person" thread of this interface object when the message is triggered. [Cpp] STDMETHODIMP _ (void) CBrowserHost: DocumentComplete (IDispatch * pDisp, VARIANT * URL) {CComPtr <IWebBrowser2> spWeb; m_webBrowser.QueryControl (scheme, (LPVOID *) & spWeb ); m_AutoMan.SetWebBrowser (spWeb);} If 12306 is loaded, only one DocumentComplete event is triggered, then we may not have to write an article here to talk about the startup of the "person" thread. Those who have observed the 12306 page should find that multiple Iframe are embedded in the page. When an Iframe is loaded, A DocumentComplete event is triggered. This leads to the classic problems in multithreaded programming: "consumers" and "Producers ". The producer here is a browser, which will create a product (IWebBrowser object) from time to time. "Consumers" are our "people" Threads. How can we make choices for so many products? Let's take a look at the producer behavior [cpp] VOID CAutoMan: SetWebBrowser (CComPtr <IWebBrowser2> & spWeb) {CoInitializeEx (NULL, COINIT_APARTMENTTHREADED); do {EnterCriticalSection (& m_cs ); CComPtr <IUnknown> spIUnknown; IStream * spIStream = NULL; HRESULT hr = spWeb-> QueryInterface (IID_IUnknown, (LPVOID *) & spIUnknown); checkhr, spIUnknown ); try {hr =: cow.alinterthreadinterfaceinstream (_ uuidof (IWebBrowser2 ), SpIUnknown, & spIStream);} catch (...) {hr = E_FAIL;} CHECKHRPOINTER (hr, spIStream); m_ListIStream.push_back (spIStream); LeaveCriticalSection (& m_cs);} while (0); CoUninitialize ();} Because of multithreading, we use the critical section m_cs to ensure orderly management of the product warehouse-m_ListIStream. We package the basic product made by the browser-codecomalinterthreadinterfaceinstream to generate a stream object. Then, place the stream object in the last position of the product library. Pay special attention to stream objects. For example, if I prefer to use ATL to manage COM, the stream object IStream * spIStream does not use CComPtr for management. Because the stream object cannot be released within the function, we need to read it in the "person" thread. The function in the "unlock package" thread is responsible for releasing it. For a "person" thread, it may process other interface objects in the product library after processing an IWebBrowser interface object. So how should we choose it? We can think of it as a person. In fact, when we browse the Web page, the browser sends many events, but we don't care about these events. We just care about the final state. -- Yes, the same is true for our "person" thread. It only cares about the last product-because it is the latest, why should we use outdated things? [Cpp] HRESULT CAutoMan: ConvertInterface () {HRESULT hr = E_FAIL; CComPtr <IWebBrowser2> spTempWebB = NULL; EnterCriticalSection (& m_cs); do {// get the last IStream, use it as the standard ListIStreamRIter iterLast = m_ListIStream.rbegin (); if (iterLast = m_ListIStream.rend () | NULL = * iterLast) {break ;} // release other IStream for (ListIStreamIter iter = m_ListIStream.begin (); iter! = M_ListIStream.end (); iter ++) {if (* iter = * iterLast | NULL = * iter) {continue;} (* iter)-> Release (); * iter = NULL;} spTempWebB = NULL; CHECKPOINT (* iterLast); try {hr = CoGetInterfaceAndReleaseStream (* iterLast), _ uuidof (IWebBrowser2), (LPVOID *) & spTempWebB);} catch (...) {hr = E_FAIL;} CHECKHRPOINTER (hr, spTempWebB); * iterLast = NULL;} while (0); m_ListIStream.clear (); LeaveCritical Section (& m_cs); if (NULL! = SpTempWebB) {m_spWindow = NULL; m_spWindow = spTempWebB;} return hr;} the above Code is clearly annotated. The "person" thread gets the last latest IStream, it is packaged to save the results in the Temporary Variable spTempWebB. It also releases other obsolete IStream interface objects in the repository. Note that I did not directly convert IStream to m_spWindow, because m_spWindow must be set to NULL before conversion. It is precisely this process of setting it to NULL that may cause deadlocks with the previous SetWebBrowser process. So here I use a temporary variable to receive the conversion result, and then set m_spWindow to this result. The code of the thread function is [cpp] VOID CAutoMan: ThreadFun () {m_dwQueryTime = QUERYTIMESLOW; while (WAIT_TIMEOUT = WaitForSingleObject (m_hStopEvent, m_dwQueryTime) {ConvertInterface (); if (NULL = m_spWindow) {continue;} CComBSTR bstrUrl; HRESULT hr = m_spWindow-> get_LocationURL (& bstrUrl); CComPtr <IHTMLDocument2> spDoc; CComPtr <IDispatch> spDispatch; hr = m_spWindow-> get_Document (& spDispatch); if (FAILED (h R) | NULL = spDispatch) {continue;} hr = spDispatch-> QueryInterface (IID_IHTMLDocument2, (LPVOID *) & spDoc); try {if (m_DealWebPage.IsQueryPage (spDoc, bstrUrl) {hr = reverse (spDoc); if (m_bStartQuery) {hr = reverse (spDoc); if (FAILED (hr) {hr = m_DealWebPage.StartQueryInQueryPage (spDoc );}} else {}} else if (m_DealWebPage.IsBooking Page (spDoc, bstrUrl) {hr = m_DealWebPage.BookTickets (spDoc); if (SUCCEEDED (hr) {// awaiting processing, exit thread} else {}} catch (...) the "persons" thread will perform polling once every m_dwQueryTime millisecond. The operation content is: 1 query the current ur l www.2cto.com 2 if the current URL is the ticket booking query page (m_DealWebPage.IsQueryPage (spDoc, bstrUrl )), perform the insert control button (hr = m_DealWebPage.InsertButtonInQueryPage (spDoc);) B to check whether there is A ticket (hr = m_DealWebPage.QueryTicketsInfo (spDoc );) c. Click the refresh button (hr = m_DealWebPage.StartQueryInQueryPage (spDoc);) if the order is confirmed (m_DealWebPage.IsBookingPage (spDoc, bstrUrl )), then the ticket booking operation (hr = m_DealWebPage.BookTickets (spDoc);) is too late, I cannot The ticket booking process is illustrated in the following illustration. This is the time to take a rest. This evening I will explain the detailed process on the page 12306.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.