title: How to automate an IE webapp that pops a modal HTML dialog?
body: <p>[<strong>Revised yet again</strong> for clarity]</p>
  
  <p>I have a C++ program which interacts with a website. The site is IE-specific, and so is my program.</p>
  
  <p>I'm connecting to the running instance of IE in an ordinary way (<em>out of process</em> -- see code). Once I get the <code>IWebBrowser2</code>, I have no problem getting the <code>IHTMLDocument2</code> and interacting with the individual <code>IHTMLElement</code> objects, filling in fields and clicking buttons.</p>
  
  <p>But if the web page has javascript that calls <a href="http://msdn.microsoft.com/en-us/library/ie/ms536759%28v=vs.85%29.aspx" rel="nofollow">window.showModalDialog</a>, I'm stuck: I need to interact with the HTML elements in the popup, just like the other pages; but I can't seem to get its <code>IWebBrowser2</code>.</p>
  
  <p>The popup is always titled "Web Page Dialog", and is a window of type <code>Internet Explorer_TridentDlgFrame</code> containing an <code>Internet Explorer_Server</code>. But I can't get the IWebBrowser2 from the <code>Internet Explorer_Server</code> window the way I can when it's a normal IE instance.</p>
  
  <p>I can get the <code>IHTMLDocument2Ptr</code>, but when I try to get the <code>IWebBrowser2</code> I get an <code>HRESULT</code> of <code>E_NOINTERFACE</code>.</p>
  
  <p>The code is pretty standard stuff, and works fine if it's a 'normal' IE window</p>
  
  <pre><code>IHTMLDocument2Ptr pDoc;
  LRESULT lRes;
  
  /* hWndChild is an instance of class "Internet Explorer_Server" */
  
  UINT nMsg = ::RegisterWindowMessage( "WM_HTML_GETOBJECT" );
  ::SendMessageTimeout( hWndChild, nMsg, 0L, 0L, SMTO_ABORTIFHUNG, 1000, 
      (DWORD*)&amp;lRes );
  
  LPFNOBJECTFROMLRESULT pfObjectFromLresult = 
      (LPFNOBJECTFROMLRESULT)::GetProcAddress( hInst, "ObjectFromLresult" );
  if ( pfObjectFromLresult != NULL )
  {
      HRESULT hr;
      hr = (*pfObjectFromLresult)( lRes, IID_IHTMLDocument, 0, (void**)&amp;pDoc );
      if ( SUCCEEDED(hr) ) {
          IServiceProvider *pService;
          hr = pDoc-&gt;QueryInterface(IID_IServiceProvider, (void **) &amp;pService);
          if ( SUCCEEDED(hr) )
          {
              hr = pService-&gt;QueryService(SID_SWebBrowserApp,
                  IID_IWebBrowser2, (void **) &amp;pBrowser);
  
              // This is where the problem occurs:
              // hr == E_NOINTERFACE
           }
      }
  }
  </code></pre>
  
  <p>In case it matters, this is <strong>Vista</strong> and <strong>IE8</strong>. (I emphasize this because both of these introduced breaking changes in my codebase, which had worked fine with XP/IE7.)</p>
  
  <p>Once again, my goal is to get each <code>IHTMLElement</code> and interact with it. I don't have access to the source code of the application which I'm automating.</p>
  
  <p>I'm considering sending keystrokes blindly to the <code>Internet Explorer_Server</code> window, but would rather not.</p>
  
  <p><strong>Edited to add:</strong></p>
  
  <p>Someone suggested getting the child windows and sending them messages, but I'm pretty sure that doesn't work with <code>Internet Explorer_Server</code>; according to Spy++, there's aren't any child windows. (This is not IE-specific. Java applets don't seem to have child windows, either.)</p>
  
  <p><strong>Update</strong></p>
  
  <p>In the comments, Simon Maurer said the above code worked for him, and just to make sure there were no typos he very generously posted a complete standalone app on <a href="http://pastebin.com/uj1nXG4S" rel="nofollow">pastebin</a>. When I used his code, it failed in the same way in the same place, and I realized he thought I wanted to connect to the <strong>underlying</strong> page, not the popup. So I've edited the text above to remove that ambiguity.</p>