Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. COM
  4. fail to get IHTMLElement from IHTMLFormElement

fail to get IHTMLElement from IHTMLFormElement

Scheduled Pinned Locked Moved COM
htmlcomannouncement
5 Posts 2 Posters 1 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • C Offline
    C Offline
    computer_nerd
    wrote on last edited by
    #1

    Hello all I am getting the form objects from internet explorer and want to get all the elements from each form. To do this, I get the form collection from the html document object, get an interface to each form element in the collection then try to get an IID_IHTMLElement interface from the IID_IHTMLFormElement interface in order to get all the elements in the form, as recommended by MS. It all works on my machine and all others I've tried, except that on my friend's pc, the QueryInterface call fails with E_NOINTERFACE. I'm not that proficient in COM, so I wonder if there is something I'm doing wrong here so that it only works on some systems. He assures me that he has IE7 installed so not an old cranky version. Code as follows:

    bool ret = true;
    CComPtr<IHTMLElementCollection> spForms;
    long numForms = 0L;
        CComPtr<IDispatch> spDisp;
    
    // get collection of forms within web page 
    HRESULT hr = spDoc->get\_forms(&spForms.p); 
    if (FAILED(hr) || !spForms)
    {
    	ret = false;
    } 
    
    if (ret)
    {
    	// get number of forms in collection
    	HRESULT hr = spForms->get\_length(&numForms);
    	if (FAILED(hr))
    	{
    		ret = false;
    	}
    }
    
    if (ret)
    {
    	// process each form
    	for (int formNumber = 0; ret && (formNumber < numForms); formNumber++)
    	{
    		BSTR bstr;
    		CString formName;
    		CComPtr<IHTMLElementCollection> spElements;
    		CComPtr<IHTMLFormElement> spFormElement;
    		CComPtr<IHTMLElement> spElement;
    		long numElements = 0L;
    
    		// get next form
    		CComVariant vIdx(0, VT\_I4); 
    		HRESULT hr = spForms->item(CComVariant(formNumber), vIdx, &spDisp.p);
    		if (FAILED(hr) || !spDisp)
    		{
    			ret = false;
    		}
    
    		if (ret)
    		{
    			// get form interface
    			HRESULT hr = spDisp->QueryInterface(
    				IID\_IHTMLFormElement, (void\*\*) &spFormElement.p);
    			if (FAILED(hr) || !spFormElement)
    			{
    				ret = false;
    			}
    		}
    
    		if (ret)
    		{
    			// get form name
    			hr = spFormElement->get\_name(&bstr);
    			if (FAILED(hr))
    			{
    				ret = false;
    			}
    		}
    
    		if (ret)
    		{
    			// need to call IHTMLElement::all() instead of IHTMLFormElement::item(),
    			// otherwise will only get the controls and not all the elements in the form,
    			// such as the labels
    			HRESULT hr = spFormElement->QueryInterface(!!!
    				IID\_IHTMLElement, (void\*\*) &spElement.p);
    			if (FAILED(hr) || !spElement)
    			{
    				// FAILS HERE WITH hr == E\_NOINTERFACE!!!
    				ret = false;
    			}
    
    J 1 Reply Last reply
    0
    • C computer_nerd

      Hello all I am getting the form objects from internet explorer and want to get all the elements from each form. To do this, I get the form collection from the html document object, get an interface to each form element in the collection then try to get an IID_IHTMLElement interface from the IID_IHTMLFormElement interface in order to get all the elements in the form, as recommended by MS. It all works on my machine and all others I've tried, except that on my friend's pc, the QueryInterface call fails with E_NOINTERFACE. I'm not that proficient in COM, so I wonder if there is something I'm doing wrong here so that it only works on some systems. He assures me that he has IE7 installed so not an old cranky version. Code as follows:

      bool ret = true;
      CComPtr<IHTMLElementCollection> spForms;
      long numForms = 0L;
          CComPtr<IDispatch> spDisp;
      
      // get collection of forms within web page 
      HRESULT hr = spDoc->get\_forms(&spForms.p); 
      if (FAILED(hr) || !spForms)
      {
      	ret = false;
      } 
      
      if (ret)
      {
      	// get number of forms in collection
      	HRESULT hr = spForms->get\_length(&numForms);
      	if (FAILED(hr))
      	{
      		ret = false;
      	}
      }
      
      if (ret)
      {
      	// process each form
      	for (int formNumber = 0; ret && (formNumber < numForms); formNumber++)
      	{
      		BSTR bstr;
      		CString formName;
      		CComPtr<IHTMLElementCollection> spElements;
      		CComPtr<IHTMLFormElement> spFormElement;
      		CComPtr<IHTMLElement> spElement;
      		long numElements = 0L;
      
      		// get next form
      		CComVariant vIdx(0, VT\_I4); 
      		HRESULT hr = spForms->item(CComVariant(formNumber), vIdx, &spDisp.p);
      		if (FAILED(hr) || !spDisp)
      		{
      			ret = false;
      		}
      
      		if (ret)
      		{
      			// get form interface
      			HRESULT hr = spDisp->QueryInterface(
      				IID\_IHTMLFormElement, (void\*\*) &spFormElement.p);
      			if (FAILED(hr) || !spFormElement)
      			{
      				ret = false;
      			}
      		}
      
      		if (ret)
      		{
      			// get form name
      			hr = spFormElement->get\_name(&bstr);
      			if (FAILED(hr))
      			{
      				ret = false;
      			}
      		}
      
      		if (ret)
      		{
      			// need to call IHTMLElement::all() instead of IHTMLFormElement::item(),
      			// otherwise will only get the controls and not all the elements in the form,
      			// such as the labels
      			HRESULT hr = spFormElement->QueryInterface(!!!
      				IID\_IHTMLElement, (void\*\*) &spElement.p);
      			if (FAILED(hr) || !spElement)
      			{
      				// FAILS HERE WITH hr == E\_NOINTERFACE!!!
      				ret = false;
      			}
      
      J Offline
      J Offline
      Jonathan Davies
      wrote on last edited by
      #2

      It doesn't sound as if there's anything wrong with your code. E_NO_INTERFACE is technically not a failure, it's a legal response in the COM world. I've had users 'assure me' that nothing out of the ordinary is installed or used when it proves not to be the case. Can you put in some checks in your code to test for the right version of IE or perhaps a version number or similar for the FormElement that you get the E_NOINTERFACE from? Does it support some alternate interface, say IHTMLElementEx? I'm not saying there is such a thing as an IHTMLElementEx interface, it's just a possibility.

      C 1 Reply Last reply
      0
      • J Jonathan Davies

        It doesn't sound as if there's anything wrong with your code. E_NO_INTERFACE is technically not a failure, it's a legal response in the COM world. I've had users 'assure me' that nothing out of the ordinary is installed or used when it proves not to be the case. Can you put in some checks in your code to test for the right version of IE or perhaps a version number or similar for the FormElement that you get the E_NOINTERFACE from? Does it support some alternate interface, say IHTMLElementEx? I'm not saying there is such a thing as an IHTMLElementEx interface, it's just a possibility.

        C Offline
        C Offline
        computer_nerd
        wrote on last edited by
        #3

        Hi I called him tonight and got him to check the IE version. It is version 7, same as mine. I also asked him to disable all add-ons temporarily but got the same problem. If we both have IE7 and add-ons are not the problem, what other difference could there be on his system that means he gets the E_NOINTERFACE and I don't?

        J 1 Reply Last reply
        0
        • C computer_nerd

          Hi I called him tonight and got him to check the IE version. It is version 7, same as mine. I also asked him to disable all add-ons temporarily but got the same problem. If we both have IE7 and add-ons are not the problem, what other difference could there be on his system that means he gets the E_NOINTERFACE and I don't?

          J Offline
          J Offline
          Jonathan Davies
          wrote on last edited by
          #4

          I suppose it depends on what he has loaded up in IE at the time. For any COM error such as E_NOINTERFACE you can look for extended error information that may have been set when the error was generated:

          //Check for IErorrInfo and load it if it is present
          IErrorInfo* pErrInfo = NULL;
          HRESULT hr = GetErrorInfo(0, &pErrInfo);

          Then use the IErrorInfo methods to obtain details, though there may be no info set to retreive its worth a try. You may have the same IE7, but presumably you may not have the same forms or elements etc. All I can suggest is have the program get details of the object that returns E_NOINTERFACE to see if you can find anything out based on that information or establish a pattern. It may be that in an ideal world all objects would implement this interface but in reality it means that you have to accept that there are objects out there that don't for some reason. As a result you have to handle the ones that don't somehow. Currently your loop exits when 'ret' becomes false for any reason, maybe you need to skip that element and move on to the next (or something similar), storing its details etc.

          C 1 Reply Last reply
          0
          • J Jonathan Davies

            I suppose it depends on what he has loaded up in IE at the time. For any COM error such as E_NOINTERFACE you can look for extended error information that may have been set when the error was generated:

            //Check for IErorrInfo and load it if it is present
            IErrorInfo* pErrInfo = NULL;
            HRESULT hr = GetErrorInfo(0, &pErrInfo);

            Then use the IErrorInfo methods to obtain details, though there may be no info set to retreive its worth a try. You may have the same IE7, but presumably you may not have the same forms or elements etc. All I can suggest is have the program get details of the object that returns E_NOINTERFACE to see if you can find anything out based on that information or establish a pattern. It may be that in an ideal world all objects would implement this interface but in reality it means that you have to accept that there are objects out there that don't for some reason. As a result you have to handle the ones that don't somehow. Currently your loop exits when 'ret' becomes false for any reason, maybe you need to skip that element and move on to the next (or something similar), storing its details etc.

            C Offline
            C Offline
            computer_nerd
            wrote on last edited by
            #5

            Thanks for that. I'll try the extended error info to see what it shows me. You're right - it should skip onto the next one if it fails instead of aborting completely. Both of us are using the same web page to test the program, specifically mailzone.onetel.net.uk which is a simple page containing a single form with a text input element and a password input element. It doesn't seem to matter what the page is though as mine always works and his always fails whatever web page I've chosen. It should be possible to get an interface to an IHTMLElement from the IHTMLFormElement according to the MS documentation, but it won't work on his pc.

            1 Reply Last reply
            0
            Reply
            • Reply as topic
            Log in to reply
            • Oldest to Newest
            • Newest to Oldest
            • Most Votes


            • Login

            • Don't have an account? Register

            • Login or register to search.
            • First post
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • World
            • Users
            • Groups